/// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="envelopeID">Envelope ID_(MAIL FROM: ENVID).</param>
        /// <param name="sender">Senders email address.</param>
        /// <param name="recipient">Recipients email address.</param>
        /// <param name="originalRecipient">Original recipient(RCPT TO: ORCPT).</param>
        /// <param name="notify">DSN notify condition.</param>
        /// <param name="ret">Specifies what parts of message are returned in DSN report.</param>
        /// <param name="date">Message date.</param>
        /// <param name="delayedDeliveryNotifySent">Specifies if delayed delivery notify has been sent.</param>
        /// <param name="hostEndPoint">Host end point where message must be sent. Value null means DNS is used to get message target host.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>sender</b> or <b>recipient</b> is null.</exception>
        /// <exception cref="ArgumentException">Is raised when any of the arguments has invalid value.</exception>
        public RelayMessageInfo(string envelopeID, string sender, string recipient, string originalRecipient, SMTP_DSN_Notify notify, SMTP_DSN_Ret ret, DateTime date, bool delayedDeliveryNotifySent, HostEndPoint hostEndPoint)
        {
            if (sender == null)
            {
                throw new ArgumentNullException("sender");
            }
            if (recipient == null)
            {
                throw new ArgumentNullException("recipient");
            }
            if (recipient == "")
            {
                throw new ArgumentException("Argument 'recipient' value must be specified.");
            }

            m_EnvelopeID        = envelopeID;
            m_Sender            = sender;
            m_Recipient         = recipient;
            m_OriginalRecipient = originalRecipient;
            m_DSN_Notify        = notify;
            m_DSN_Ret           = ret;
            m_Date = date;
            m_DelayedDeliveryNotifySent = delayedDeliveryNotifySent;
            m_pHostEndPoint             = hostEndPoint;
        }
Пример #2
0
        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="mailbox">Mailbox value.</param>
        /// <param name="size">SIZE parameter value.</param>
        /// <param name="body">BODY parameter value.</param>
        /// <param name="ret">DSN RET parameter value.</param>
        /// <param name="envid">DSN ENVID parameter value.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>mailbox</b> is null reference.</exception>
        public SMTP_MailFrom(string mailbox,int size,string body,SMTP_DSN_Ret ret,string envid)
        {
            if(mailbox == null){
                throw new ArgumentNullException("mailbox");
            }

            m_Mailbox = mailbox;
            m_Size    = size;
            m_Body    = body;
            m_RET     = ret;
            m_ENVID   = envid;
        }
Пример #3
0
 /// <summary>
 /// Default constructor.
 /// </summary>
 /// <param name="queue">Item owner queue.</param>
 /// <param name="from">Sender address.</param>
 /// <param name="envelopeID">Envelope ID_(MAIL FROM: ENVID).</param>
 /// <param name="ret">Specifies what parts of message are returned in DSN report.</param>
 /// <param name="to">Target recipient address.</param>
 /// <param name="originalRecipient">Original recipient(RCPT TO: ORCPT).</param>
 /// <param name="notify">DSN notify condition.</param>
 /// <param name="messageID">Message ID.</param>
 /// <param name="message">Raw mime message. Message reading starts from current position.</param>
 /// <param name="tag">User data.</param>
 internal Relay_QueueItem(Relay_Queue queue, string from, string envelopeID, SMTP_DSN_Ret ret, string to, string originalRecipient, SMTP_DSN_Notify notify, string messageID, Stream message, object tag)
 {
     m_pQueue            = queue;
     m_From              = from;
     m_EnvelopeID        = envelopeID;
     m_DSN_Ret           = ret;
     m_To                = to;
     m_OriginalRecipient = originalRecipient;
     m_DSN_Notify        = notify;
     m_MessageID         = messageID;
     m_pMessageStream    = message;
     m_pTag              = tag;
 }
Пример #4
0
 /// <summary>
 /// Default constructor.
 /// </summary>
 /// <param name="queue">Item owner queue.</param>
 /// <param name="from">Sender address.</param>
 /// <param name="envelopeID">Envelope ID_(MAIL FROM: ENVID).</param>
 /// <param name="ret">Specifies what parts of message are returned in DSN report.</param>
 /// <param name="to">Target recipient address.</param>
 /// <param name="originalRecipient">Original recipient(RCPT TO: ORCPT).</param>
 /// <param name="notify">DSN notify condition.</param>
 /// <param name="messageID">Message ID.</param>
 /// <param name="message">Raw mime message. Message reading starts from current position.</param>
 /// <param name="tag">User data.</param>
 internal Relay_QueueItem(Relay_Queue queue,string from,string envelopeID,SMTP_DSN_Ret ret,string to,string originalRecipient,SMTP_DSN_Notify notify,string messageID,Stream message,object tag)
 {
     m_pQueue            = queue;
     m_From              = from;
     m_EnvelopeID        = envelopeID;
     m_DSN_Ret           = ret;
     m_To                = to;
     m_OriginalRecipient = originalRecipient;
     m_DSN_Notify        = notify;
     m_MessageID         = messageID;
     m_pMessageStream    = message;
     m_pTag              = tag;
 }
Пример #5
0
        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="mailbox">Mailbox value.</param>
        /// <param name="size">SIZE parameter value.</param>
        /// <param name="body">BODY parameter value.</param>
        /// <param name="ret">DSN RET parameter value.</param>
        /// <param name="envid">DSN ENVID parameter value.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>mailbox</b> is null reference.</exception>
        public SMTP_MailFrom(string mailbox, int size, string body, SMTP_DSN_Ret ret, string envid)
        {
            if (mailbox == null)
            {
                throw new ArgumentNullException("mailbox");
            }

            m_Mailbox = mailbox;
            m_Size    = size;
            m_Body    = body;
            m_RET     = ret;
            m_ENVID   = envid;
        }
Пример #6
0
        /// <summary>
        /// Queues message for relay.
        /// </summary>
        /// <param name="from">Sender address.</param>
        /// <param name="envelopeID">Envelope ID_(MAIL FROM: ENVID).</param>
        /// <param name="ret">Specifies what parts of message are returned in DSN report.</param>
        /// <param name="to">Target recipient address.</param>
        /// <param name="originalRecipient">Original recipient(RCPT TO: ORCPT).</param>
        /// <param name="notify">DSN notify condition.</param>
        /// <param name="messageID">Message ID.</param>
        /// <param name="message">Raw mime message. Message reading starts from current position.</param>
        /// <param name="tag">User data.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>to</b>,<b>to</b>,<b>messageID</b> or <b>message</b> is null.</exception>
        /// <exception cref="ArgumentException">Is raised when any of the arguments has invalid value.</exception>
        public void QueueMessage(string from,string envelopeID,SMTP_DSN_Ret ret,string to,string originalRecipient,SMTP_DSN_Notify notify,string messageID,Stream message,object tag)
        {
            if(messageID == null){
                throw new ArgumentNullException("messageID");
            }
            if(messageID == ""){
                throw new ArgumentException("Argument 'messageID' value must be specified.");
            }
            if(message == null){
                throw new ArgumentNullException("message");
            }

            lock(m_pQueue){
                m_pQueue.Enqueue(new Relay_QueueItem(this,from,envelopeID,ret,to,originalRecipient,notify,messageID,message,tag));
            }
        }
Пример #7
0
        /// <summary>
        /// Queues message for relay.
        /// </summary>
        /// <param name="from">Sender address.</param>
        /// <param name="envelopeID">Envelope ID_(MAIL FROM: ENVID).</param>
        /// <param name="ret">Specifies what parts of message are returned in DSN report.</param>
        /// <param name="to">Target recipient address.</param>
        /// <param name="originalRecipient">Original recipient(RCPT TO: ORCPT).</param>
        /// <param name="notify">DSN notify condition.</param>
        /// <param name="messageID">Message ID.</param>
        /// <param name="message">Raw mime message. Message reading starts from current position.</param>
        /// <param name="tag">User data.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>to</b>,<b>to</b>,<b>messageID</b> or <b>message</b> is null.</exception>
        /// <exception cref="ArgumentException">Is raised when any of the arguments has invalid value.</exception>
        public void QueueMessage(string from, string envelopeID, SMTP_DSN_Ret ret, string to, string originalRecipient, SMTP_DSN_Notify notify, string messageID, Stream message, object tag)
        {
            if (messageID == null)
            {
                throw new ArgumentNullException("messageID");
            }
            if (messageID == "")
            {
                throw new ArgumentException("Argument 'messageID' value must be specified.");
            }
            if (message == null)
            {
                throw new ArgumentNullException("message");
            }

            lock (m_pQueue){
                m_pQueue.Enqueue(new Relay_QueueItem(this, from, envelopeID, ret, to, originalRecipient, notify, messageID, message, tag));
            }
        }
Пример #8
0
        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="envelopeID">Envelope ID_(MAIL FROM: ENVID).</param>
        /// <param name="sender">Senders email address.</param>
        /// <param name="recipient">Recipients email address.</param>
        /// <param name="originalRecipient">Original recipient(RCPT TO: ORCPT).</param>
        /// <param name="notify">DSN notify condition.</param>
        /// <param name="ret">Specifies what parts of message are returned in DSN report.</param>
        /// <param name="date">Message date.</param>
        /// <param name="delayedDeliveryNotifySent">Specifies if delayed delivery notify has been sent.</param>
        /// <param name="hostEndPoint">Host end point where message must be sent. Value null means DNS is used to get message target host.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>sender</b> or <b>recipient</b> is null.</exception>
        /// <exception cref="ArgumentException">Is raised when any of the arguments has invalid value.</exception>
        public RelayMessageInfo(string envelopeID,string sender,string recipient,string originalRecipient,SMTP_DSN_Notify notify,SMTP_DSN_Ret ret,DateTime date,bool delayedDeliveryNotifySent,HostEndPoint hostEndPoint)
        {
            if(sender == null){
                throw new ArgumentNullException("sender");
            }
            if(recipient == null){
                throw new ArgumentNullException("recipient");
            }
            if(recipient == ""){
                throw new ArgumentException("Argument 'recipient' value must be specified.");
            }

            m_EnvelopeID                = envelopeID;
            m_Sender                    = sender;
            m_Recipient                 = recipient;
            m_OriginalRecipient         = originalRecipient;
            m_DSN_Notify                = notify;
            m_DSN_Ret                   = ret;
            m_Date                      = date;
            m_DelayedDeliveryNotifySent = delayedDeliveryNotifySent;
            m_pHostEndPoint             = hostEndPoint;
        }
Пример #9
0
        /// <summary>
        /// Stores message for relay.
        /// </summary>
        /// <param name="queueName">Queue name where to store message.</param>
        /// <param name="id">Message ID. Guid value is suggested.</param>
        /// <param name="envelopeID">Envelope ID_(MAIL FROM: ENVID).</param>
        /// <param name="date">Message date.</param>
        /// <param name="message">Message to store. Message will be readed from current position of stream.</param>
        /// <param name="targetHost">Target host or IP where to send message. This value can be null, then DNS MX o A record is used to deliver message.</param>
        /// <param name="sender">Sender address to report to target server.</param>
        /// <param name="to">Message recipient address.</param>
        /// <param name="originalRecipient">Original recipient(RCPT TO: ORCPT).</param>
        /// <param name="notify">DSN notify condition.</param>
        /// <param name="ret">Specifies what parts of message are returned in DSN report.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>queueName</b>,<b>id</b>,<b>message</b> or <b>to</b> is null.</exception>
        /// <exception cref="ArgumentException">Is raised when any of the argumnets has invalid value.</exception>
        private void StoreRelayMessage(string queueName,string id,string envelopeID,DateTime date,Stream message,HostEndPoint targetHost,string sender,string to,string originalRecipient,SMTP_DSN_Notify notify,SMTP_DSN_Ret ret)
        {
            if(queueName == null){
                throw new ArgumentNullException("queueName");
            }
            if(queueName == ""){
                throw new ArgumentException("Argumnet 'queueName' value must be specified.");
            }
            if(id == null){
                throw new ArgumentNullException("id");
            }
            if(id == ""){
                throw new ArgumentException("Argument 'id' value must be specified.");
            }
            if(message == null){
                throw new ArgumentNullException("message");
            }
            if(to == null){
                throw new ArgumentNullException("to");
            }
            if(to == ""){
                throw new ArgumentException("Argument 'to' value must be specified.");
            }
					
			string path = m_pVirtualServer.MailStorePath + queueName;

			// Check if Directory exists, if not Create
			if(!Directory.Exists(path)){
				Directory.CreateDirectory(path);
			}

			// Create relay message.
			using(FileStream fs = File.Create(API_Utlis.PathFix(path + "\\" + id + ".eml"))){
                SCore.StreamCopy(message,fs);
                               
                // Create message info file for the specified relay message.
                RelayMessageInfo messageInfo = new RelayMessageInfo(
                    envelopeID,
                    sender,
                    to,
                    originalRecipient,
                    notify,
                    ret,
                    date,
                    false,
                    targetHost
                );
                File.WriteAllBytes(API_Utlis.PathFix(path + "\\" + id + ".info"),messageInfo.ToByte());
			}
        }
 /// <summary>
 /// Queues message for relay.
 /// </summary>
 /// <param name="from">Sender address.</param>
 /// <param name="envelopeID">Envelope ID_(MAIL FROM: ENVID).</param>
 /// <param name="ret">Specifies what parts of message are returned in DSN report.</param>
 /// <param name="to">Target recipient address.</param>
 /// <param name="originalRecipient">Original recipient(RCPT TO: ORCPT).</param>
 /// <param name="notify">DSN notify condition.</param>
 /// <param name="messageID">Message ID.</param>
 /// <param name="message">Raw mime message. Message reading starts from current position.</param>
 /// <param name="tag">User data.</param>
 /// <exception cref="ArgumentNullException">Is raised when <b>to</b>,<b>to</b>,<b>messageID</b> or <b>message</b> is null.</exception>
 /// <exception cref="ArgumentException">Is raised when any of the arguments has invalid value.</exception>
 public void QueueMessage(string from, string envelopeID, SMTP_DSN_Ret ret, string to, string originalRecipient, SMTP_DSN_Notify notify, string messageID, Stream message, object tag)
 {
     QueueMessage(null, from, envelopeID, ret, to, originalRecipient, notify, messageID, message, tag);
 }
        public static Mail_Message CreateDsnMessage(string to, string subject, string rtfText, string envelopeID, DateTime arrivalDate, string receivedFromMTA, string reportingMTA, string originalRecipient, string finalRecipient, string action, string statusCode_text, string remoteMTA, DateTime lastAttempt, DateTime retryUntil, SMTP_DSN_Ret ret, Mail_Message message)
        {
            rtfText = rtfText.Replace("\r\n", "\n").Replace("\n", "\r\n");
            Mail_Message mail_Message = new Mail_Message();

            mail_Message.MimeVersion = "1.0";
            mail_Message.Date        = DateTime.Now;
            mail_Message.From        = new Mail_t_MailboxList();
            mail_Message.From.Add(new Mail_t_Mailbox("Mail Delivery Subsystem", "postmaster@local"));
            mail_Message.To = new Mail_t_AddressList();
            mail_Message.To.Add(new Mail_t_Mailbox(null, to));
            mail_Message.Subject = subject;
            MIME_h_ContentType mIME_h_ContentType = new MIME_h_ContentType(MIME_MediaTypes.Multipart.report);

            mIME_h_ContentType.Parameters["report-type"] = "delivery-status";
            mIME_h_ContentType.Param_Boundary            = Guid.NewGuid().ToString().Replace('-', '.');
            MIME_b_MultipartReport mIME_b_MultipartReport = new MIME_b_MultipartReport(mIME_h_ContentType);

            mail_Message.Body = mIME_b_MultipartReport;
            MIME_Entity mIME_Entity = new MIME_Entity();
            MIME_b_MultipartAlternative mIME_b_MultipartAlternative = new MIME_b_MultipartAlternative(new MIME_h_ContentType(MIME_MediaTypes.Multipart.alternative)
            {
                Param_Boundary = Guid.NewGuid().ToString().Replace('-', '.')
            });

            mIME_Entity.Body = mIME_b_MultipartAlternative;
            mIME_b_MultipartReport.BodyParts.Add(mIME_Entity);
            MIME_Entity mIME_Entity2 = new MIME_Entity();
            MIME_b_Text mIME_b_Text  = new MIME_b_Text(MIME_MediaTypes.Text.plain);

            mIME_Entity2.Body = mIME_b_Text;
            mIME_b_Text.SetText(MIME_TransferEncodings.QuotedPrintable, Encoding.UTF8, SCore.RtfToText(rtfText));
            mIME_b_MultipartAlternative.BodyParts.Add(mIME_Entity2);
            MIME_Entity mIME_Entity3 = new MIME_Entity();
            MIME_b_Text mIME_b_Text2 = new MIME_b_Text(MIME_MediaTypes.Text.html);

            mIME_Entity3.Body = mIME_b_Text2;
            mIME_b_Text2.SetText(MIME_TransferEncodings.QuotedPrintable, Encoding.UTF8, SCore.RtfToHtml(rtfText));
            mIME_b_MultipartAlternative.BodyParts.Add(mIME_Entity3);
            MIME_Entity    mIME_Entity4   = new MIME_Entity();
            MIME_b_Message mIME_b_Message = new MIME_b_Message(MIME_MediaTypes.Message.delivery_status);

            mIME_Entity4.Body = mIME_b_Message;
            StringBuilder stringBuilder = new StringBuilder();

            if (!string.IsNullOrEmpty(envelopeID))
            {
                stringBuilder.Append("Original-Envelope-Id: " + envelopeID + "\r\n");
            }
            stringBuilder.Append("Arrival-Date: " + MIME_Utils.DateTimeToRfc2822(arrivalDate) + "\r\n");
            if (!string.IsNullOrEmpty(receivedFromMTA))
            {
                stringBuilder.Append("Received-From-MTA: dns; " + receivedFromMTA + "\r\n");
            }
            stringBuilder.Append("Reporting-MTA: dns; " + reportingMTA + "\r\n");
            stringBuilder.Append("\r\n");
            if (!string.IsNullOrEmpty(originalRecipient))
            {
                stringBuilder.Append("Original-Recipient: " + originalRecipient + "\r\n");
            }
            stringBuilder.Append("Final-Recipient: rfc822;" + finalRecipient + "\r\n");
            stringBuilder.Append("Action: " + action + "\r\n");
            stringBuilder.Append("Status: " + statusCode_text.Substring(0, 1) + ".0.0\r\n");
            if (!string.IsNullOrEmpty(statusCode_text))
            {
                stringBuilder.Append("Diagnostic-Code: smtp; " + statusCode_text + "\r\n");
            }
            if (!string.IsNullOrEmpty(remoteMTA))
            {
                stringBuilder.Append("Remote-MTA: dns; " + remoteMTA + "\r\n");
            }
            if (lastAttempt != DateTime.MinValue)
            {
                stringBuilder.Append("Last-Attempt-Date: " + MIME_Utils.DateTimeToRfc2822(lastAttempt) + "\r\n");
            }
            if (retryUntil != DateTime.MinValue)
            {
                stringBuilder.Append("Will-Retry-Until: " + MIME_Utils.DateTimeToRfc2822(retryUntil) + "\r\n");
            }
            stringBuilder.Append("\r\n");
            mIME_b_Message.SetData(new MemoryStream(Encoding.UTF8.GetBytes(stringBuilder.ToString())), MIME_TransferEncodings.EightBit);
            mIME_b_MultipartReport.BodyParts.Add(mIME_Entity4);
            if (message != null)
            {
                MIME_Entity          mIME_Entity5      = new MIME_Entity();
                MIME_b_MessageRfc822 mIME_b_MessageRfc = new MIME_b_MessageRfc822();
                mIME_Entity5.Body = mIME_b_MessageRfc;
                if (ret == SMTP_DSN_Ret.FullMessage)
                {
                    mIME_b_MessageRfc.Message = message;
                }
                else
                {
                    MemoryStream memoryStream = new MemoryStream();
                    message.Header.ToStream(memoryStream, null, null);
                    memoryStream.Position     = 0L;
                    mIME_b_MessageRfc.Message = Mail_Message.ParseFromStream(memoryStream);
                }
                mIME_b_MultipartReport.BodyParts.Add(mIME_Entity5);
            }
            return(mail_Message);
        }
Пример #12
0
 /// <summary>
 /// Stores message for relay.
 /// </summary>
 /// <param name="id">Message ID. Guid value is suggested.</param>
 /// <param name="envelopeID">Envelope ID_(MAIL FROM: ENVID).</param>
 /// <param name="message">Message to store. Message will be readed from current position of stream.</param>
 /// <param name="targetHost">Target host or IP where to send message. This value can be null, then DNS MX o A record is used to deliver message.</param>
 /// <param name="sender">Sender address to report to target server.</param>
 /// <param name="to">Message recipient address.</param>
 /// <param name="originalRecipient">Original recipient(RCPT TO: ORCPT).</param>
 /// <param name="notify">DSN notify condition.</param>
 /// <param name="ret">Specifies what parts of message are returned in DSN report.</param>
 /// <exception cref="ArgumentNullException">Is raised when <b>id</b>,<b>message</b> or <b>to</b> is null.</exception>
 /// <exception cref="ArgumentException">Is raised when any of the argumnets has invalid value.</exception>
 public void StoreRelayMessage(string id, String envelopeID, Stream message, HostEndPoint targetHost, string sender, string to, string originalRecipient, SMTP_DSN_Notify notify, SMTP_DSN_Ret ret)
 {
     StoreRelayMessage("Relay", id, envelopeID, DateTime.Now, message, targetHost, sender, to, originalRecipient, notify, ret);
 }
Пример #13
0
        /// <summary>
        /// Creates delivery status notifications(DSN) message. 
        /// </summary>
        /// <param name="to">DSN message To.</param>
        /// <param name="subject">DSN message subject.</param>
        /// <param name="rtfText">DSN message RTF body text.</param>
        /// <param name="envelopeID">Envelope ID(MAIL FROM: ENVID).</param>
        /// <param name="arrivalDate">Message arrival date.</param>
        /// <param name="receivedFromMTA">The remote host EHLo name from where messages was received.</param>
        /// <param name="reportingMTA">Reporting MTA name.</param>
        /// <param name="originalRecipient">Original recipient(RCPT TO: ORCTP).</param>
        /// <param name="finalRecipient">Final recipient.</param>
        /// <param name="action">DSN action.</param>
        /// <param name="statusCode_text">Remote SMTP status code with text.</param>
        /// <param name="remoteMTA">Remote MTA what returned <b>statusCode_text</b>.</param>
        /// <param name="lastAttempt">Last delivery attempt.</param>
        /// <param name="retryUntil">Date time how long server will attempt to deliver message.</param>
        /// <param name="ret">Specifies what original message part are renturned.</param>
        /// <param name="message">Original message.</param>
        /// <returns>Returns created DSN message.</returns>
        public static Mail_Message CreateDsnMessage(string to,string subject,string rtfText,string envelopeID,DateTime arrivalDate,string receivedFromMTA,string reportingMTA,string originalRecipient,string finalRecipient,string action,string statusCode_text,string remoteMTA,DateTime lastAttempt,DateTime retryUntil,SMTP_DSN_Ret ret,Mail_Message message)
        {
            // For more info, see RFC 3464.

            // Ensure that all line-feeds are CRLF.
            rtfText = rtfText.Replace("\r\n","\n").Replace("\n","\r\n");

            Mail_Message msg = new Mail_Message();
            msg.MimeVersion = "1.0";
            msg.Date = DateTime.Now;
            msg.From = new Mail_t_MailboxList();
            msg.From.Add(new Mail_t_Mailbox("Mail Delivery Subsystem","postmaster@local"));
            msg.To = new Mail_t_AddressList();
            msg.To.Add(new Mail_t_Mailbox(null,to));
            msg.Subject = subject;

            //--- multipart/report -------------------------------------------------------------------------------------------------
            MIME_h_ContentType contentType_multipartReport = new MIME_h_ContentType(MIME_MediaTypes.Multipart.report);            
            contentType_multipartReport.Parameters["report-type"] = "delivery-status";
            contentType_multipartReport.Param_Boundary = Guid.NewGuid().ToString().Replace('-','.');
            MIME_b_MultipartReport multipartReport = new MIME_b_MultipartReport(contentType_multipartReport);
            msg.Body = multipartReport;

                //--- multipart/alternative -----------------------------------------------------------------------------------------
                MIME_Entity entity_multipart_alternative = new MIME_Entity();
                MIME_h_ContentType contentType_multipartAlternative = new MIME_h_ContentType(MIME_MediaTypes.Multipart.alternative);
                contentType_multipartAlternative.Param_Boundary = Guid.NewGuid().ToString().Replace('-','.');
                MIME_b_MultipartAlternative multipartAlternative = new MIME_b_MultipartAlternative(contentType_multipartAlternative);
                entity_multipart_alternative.Body = multipartAlternative;
                multipartReport.BodyParts.Add(entity_multipart_alternative);

                    //--- text/plain ---------------------------------------------------------------------------------------------------
                    MIME_Entity entity_text_plain = new MIME_Entity();
                    MIME_b_Text text_plain = new MIME_b_Text(MIME_MediaTypes.Text.plain);
                    entity_text_plain.Body = text_plain;
                    text_plain.SetText(MIME_TransferEncodings.QuotedPrintable,Encoding.UTF8,SCore.RtfToText(rtfText));
                    multipartAlternative.BodyParts.Add(entity_text_plain);

                    //--- text/html -----------------------------------------------------------------------------------------------------
                    MIME_Entity entity_text_html = new MIME_Entity();
                    MIME_b_Text text_html = new MIME_b_Text(MIME_MediaTypes.Text.html);
                    entity_text_html.Body = text_html;
                    text_html.SetText(MIME_TransferEncodings.QuotedPrintable,Encoding.UTF8,SCore.RtfToHtml(rtfText));
                    multipartAlternative.BodyParts.Add(entity_text_html);

                //--- message/delivery-status
                MIME_Entity entity_message_deliveryStatus = new MIME_Entity();
                MIME_b_Message body_message_deliveryStatus = new MIME_b_Message(MIME_MediaTypes.Message.delivery_status);
                entity_message_deliveryStatus.Body = body_message_deliveryStatus;                
                StringBuilder dsnText = new StringBuilder();
                if(!string.IsNullOrEmpty(envelopeID)){
                    dsnText.Append("Original-Envelope-Id: " + envelopeID + "\r\n");
                }
                dsnText.Append("Arrival-Date: " + MIME_Utils.DateTimeToRfc2822(arrivalDate) + "\r\n");
                if(!string.IsNullOrEmpty(receivedFromMTA)){
                    dsnText.Append("Received-From-MTA: dns; " + receivedFromMTA + "\r\n");
                }
                dsnText.Append("Reporting-MTA: dns; " + reportingMTA + "\r\n");
                dsnText.Append("\r\n");
                if(!string.IsNullOrEmpty(originalRecipient)){
                    dsnText.Append("Original-Recipient: " + originalRecipient + "\r\n");
                }
                dsnText.Append("Final-Recipient: rfc822;" + finalRecipient + "" + "\r\n");
                dsnText.Append("Action: " + action + "\r\n");
                dsnText.Append("Status: " + statusCode_text.Substring(0,1) + ".0.0" + "\r\n");
                if(!string.IsNullOrEmpty(statusCode_text)){
                    dsnText.Append("Diagnostic-Code: smtp; " + statusCode_text + "\r\n");
                }
                if(!string.IsNullOrEmpty(remoteMTA)){
                    dsnText.Append("Remote-MTA: dns; " + remoteMTA + "\r\n");
                }
                if(lastAttempt != DateTime.MinValue){
                    dsnText.Append("Last-Attempt-Date: " + MIME_Utils.DateTimeToRfc2822(lastAttempt) + "\r\n");
                }
                if(retryUntil != DateTime.MinValue){
                    dsnText.Append("Will-Retry-Until: " + MIME_Utils.DateTimeToRfc2822(retryUntil) + "\r\n");
                }
                dsnText.Append("\r\n");
                body_message_deliveryStatus.SetData(new MemoryStream(Encoding.UTF8.GetBytes(dsnText.ToString())),MIME_TransferEncodings.EightBit);
                multipartReport.BodyParts.Add(entity_message_deliveryStatus);

                //--- message/rfc822
                if(message != null){
                    MIME_Entity entity_message_rfc822 = new MIME_Entity();
                    MIME_b_MessageRfc822 body_message_rfc822 = new MIME_b_MessageRfc822();
                    entity_message_rfc822.Body = body_message_rfc822;
                    if(ret == SMTP_DSN_Ret.FullMessage){
                        body_message_rfc822.Message = message;
                    }
                    else{
                        MemoryStream ms = new MemoryStream();
                        message.Header.ToStream(ms,null,null);
                        ms.Position = 0;
                        body_message_rfc822.Message = Mail_Message.ParseFromStream(ms);
                    }                    
                    multipartReport.BodyParts.Add(entity_message_rfc822);
                }

            return msg;
        }
Пример #14
0
        /// <summary>
        /// Stores message for relay.
        /// </summary>
        /// <param name="queueName">Queue name where to store message.</param>
        /// <param name="id">Message ID. Guid value is suggested.</param>
        /// <param name="envelopeID">Envelope ID_(MAIL FROM: ENVID).</param>
        /// <param name="date">Message date.</param>
        /// <param name="message">Message to store. Message will be readed from current position of stream.</param>
        /// <param name="targetHost">Target host or IP where to send message. This value can be null, then DNS MX o A record is used to deliver message.</param>
        /// <param name="sender">Sender address to report to target server.</param>
        /// <param name="to">Message recipient address.</param>
        /// <param name="originalRecipient">Original recipient(RCPT TO: ORCPT).</param>
        /// <param name="notify">DSN notify condition.</param>
        /// <param name="ret">Specifies what parts of message are returned in DSN report.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>queueName</b>,<b>id</b>,<b>message</b> or <b>to</b> is null.</exception>
        /// <exception cref="ArgumentException">Is raised when any of the argumnets has invalid value.</exception>
        private void StoreRelayMessage(string queueName, string id, string envelopeID, DateTime date, Stream message, HostEndPoint targetHost, string sender, string to, string originalRecipient, SMTP_DSN_Notify notify, SMTP_DSN_Ret ret)
        {
            if (queueName == null)
            {
                throw new ArgumentNullException("queueName");
            }
            if (queueName == "")
            {
                throw new ArgumentException("Argumnet 'queueName' value must be specified.");
            }
            if (id == null)
            {
                throw new ArgumentNullException("id");
            }
            if (id == "")
            {
                throw new ArgumentException("Argument 'id' value must be specified.");
            }
            if (message == null)
            {
                throw new ArgumentNullException("message");
            }
            if (to == null)
            {
                throw new ArgumentNullException("to");
            }
            if (to == "")
            {
                throw new ArgumentException("Argument 'to' value must be specified.");
            }

            string path = m_pVirtualServer.MailStorePath + queueName;

            // Check if Directory exists, if not Create
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }

            // Create relay message.
            using (FileStream fs = File.Create(API_Utlis.PathFix(path + "\\" + id + ".eml"))){
                SCore.StreamCopy(message, fs);

                // Create message info file for the specified relay message.
                RelayMessageInfo messageInfo = new RelayMessageInfo(
                    envelopeID,
                    sender,
                    to,
                    originalRecipient,
                    notify,
                    ret,
                    date,
                    false,
                    targetHost
                    );
                File.WriteAllBytes(API_Utlis.PathFix(path + "\\" + id + ".info"), messageInfo.ToByte());
            }
        }
Пример #15
0
        /// <summary>
        /// Creates delivery status notifications(DSN) message.
        /// </summary>
        /// <param name="to">DSN message To.</param>
        /// <param name="subject">DSN message subject.</param>
        /// <param name="rtfText">DSN message RTF body text.</param>
        /// <param name="envelopeID">Envelope ID(MAIL FROM: ENVID).</param>
        /// <param name="arrivalDate">Message arrival date.</param>
        /// <param name="receivedFromMTA">The remote host EHLo name from where messages was received.</param>
        /// <param name="reportingMTA">Reporting MTA name.</param>
        /// <param name="originalRecipient">Original recipient(RCPT TO: ORCTP).</param>
        /// <param name="finalRecipient">Final recipient.</param>
        /// <param name="action">DSN action.</param>
        /// <param name="statusCode_text">Remote SMTP status code with text.</param>
        /// <param name="remoteMTA">Remote MTA what returned <b>statusCode_text</b>.</param>
        /// <param name="lastAttempt">Last delivery attempt.</param>
        /// <param name="retryUntil">Date time how long server will attempt to deliver message.</param>
        /// <param name="ret">Specifies what original message part are renturned.</param>
        /// <param name="message">Original message.</param>
        /// <returns>Returns created DSN message.</returns>
        public static Mail_Message CreateDsnMessage(string to, string subject, string rtfText, string envelopeID, DateTime arrivalDate, string receivedFromMTA, string reportingMTA, string originalRecipient, string finalRecipient, string action, string statusCode_text, string remoteMTA, DateTime lastAttempt, DateTime retryUntil, SMTP_DSN_Ret ret, Mail_Message message)
        {
            // For more info, see RFC 3464.

            // Ensure that all line-feeds are CRLF.
            rtfText = rtfText.Replace("\r\n", "\n").Replace("\n", "\r\n");

            Mail_Message msg = new Mail_Message();

            msg.MimeVersion = "1.0";
            msg.Date        = DateTime.Now;
            msg.From        = new Mail_t_MailboxList();
            msg.From.Add(new Mail_t_Mailbox("Mail Delivery Subsystem", "postmaster@local"));
            msg.To = new Mail_t_AddressList();
            msg.To.Add(new Mail_t_Mailbox(null, to));
            msg.Subject = subject;

            //--- multipart/report -------------------------------------------------------------------------------------------------
            MIME_h_ContentType contentType_multipartReport = new MIME_h_ContentType(MIME_MediaTypes.Multipart.report);

            contentType_multipartReport.Parameters["report-type"] = "delivery-status";
            contentType_multipartReport.Param_Boundary            = Guid.NewGuid().ToString().Replace('-', '.');
            MIME_b_MultipartReport multipartReport = new MIME_b_MultipartReport(contentType_multipartReport);

            msg.Body = multipartReport;

            //--- multipart/alternative -----------------------------------------------------------------------------------------
            MIME_Entity        entity_multipart_alternative     = new MIME_Entity();
            MIME_h_ContentType contentType_multipartAlternative = new MIME_h_ContentType(MIME_MediaTypes.Multipart.alternative);

            contentType_multipartAlternative.Param_Boundary = Guid.NewGuid().ToString().Replace('-', '.');
            MIME_b_MultipartAlternative multipartAlternative = new MIME_b_MultipartAlternative(contentType_multipartAlternative);

            entity_multipart_alternative.Body = multipartAlternative;
            multipartReport.BodyParts.Add(entity_multipart_alternative);

            //--- text/plain ---------------------------------------------------------------------------------------------------
            MIME_Entity entity_text_plain = new MIME_Entity();
            MIME_b_Text text_plain        = new MIME_b_Text(MIME_MediaTypes.Text.plain);

            entity_text_plain.Body = text_plain;
            text_plain.SetText(MIME_TransferEncodings.QuotedPrintable, Encoding.UTF8, SCore.RtfToText(rtfText));
            multipartAlternative.BodyParts.Add(entity_text_plain);

            //--- text/html -----------------------------------------------------------------------------------------------------
            MIME_Entity entity_text_html = new MIME_Entity();
            MIME_b_Text text_html        = new MIME_b_Text(MIME_MediaTypes.Text.html);

            entity_text_html.Body = text_html;
            text_html.SetText(MIME_TransferEncodings.QuotedPrintable, Encoding.UTF8, SCore.RtfToHtml(rtfText));
            multipartAlternative.BodyParts.Add(entity_text_html);

            //--- message/delivery-status
            MIME_Entity    entity_message_deliveryStatus = new MIME_Entity();
            MIME_b_Message body_message_deliveryStatus   = new MIME_b_Message(MIME_MediaTypes.Message.delivery_status);

            entity_message_deliveryStatus.Body = body_message_deliveryStatus;
            StringBuilder dsnText = new StringBuilder();

            if (!string.IsNullOrEmpty(envelopeID))
            {
                dsnText.Append("Original-Envelope-Id: " + envelopeID + "\r\n");
            }
            dsnText.Append("Arrival-Date: " + MIME_Utils.DateTimeToRfc2822(arrivalDate) + "\r\n");
            if (!string.IsNullOrEmpty(receivedFromMTA))
            {
                dsnText.Append("Received-From-MTA: dns; " + receivedFromMTA + "\r\n");
            }
            dsnText.Append("Reporting-MTA: dns; " + reportingMTA + "\r\n");
            dsnText.Append("\r\n");
            if (!string.IsNullOrEmpty(originalRecipient))
            {
                dsnText.Append("Original-Recipient: " + originalRecipient + "\r\n");
            }
            dsnText.Append("Final-Recipient: rfc822;" + finalRecipient + "" + "\r\n");
            dsnText.Append("Action: " + action + "\r\n");
            dsnText.Append("Status: " + statusCode_text.Substring(0, 1) + ".0.0" + "\r\n");
            if (!string.IsNullOrEmpty(statusCode_text))
            {
                dsnText.Append("Diagnostic-Code: smtp; " + statusCode_text + "\r\n");
            }
            if (!string.IsNullOrEmpty(remoteMTA))
            {
                dsnText.Append("Remote-MTA: dns; " + remoteMTA + "\r\n");
            }
            if (lastAttempt != DateTime.MinValue)
            {
                dsnText.Append("Last-Attempt-Date: " + MIME_Utils.DateTimeToRfc2822(lastAttempt) + "\r\n");
            }
            if (retryUntil != DateTime.MinValue)
            {
                dsnText.Append("Will-Retry-Until: " + MIME_Utils.DateTimeToRfc2822(retryUntil) + "\r\n");
            }
            dsnText.Append("\r\n");
            body_message_deliveryStatus.SetData(new MemoryStream(Encoding.UTF8.GetBytes(dsnText.ToString())), MIME_TransferEncodings.EightBit);
            multipartReport.BodyParts.Add(entity_message_deliveryStatus);

            //--- message/rfc822
            if (message != null)
            {
                MIME_Entity          entity_message_rfc822 = new MIME_Entity();
                MIME_b_MessageRfc822 body_message_rfc822   = new MIME_b_MessageRfc822();
                entity_message_rfc822.Body = body_message_rfc822;
                if (ret == SMTP_DSN_Ret.FullMessage)
                {
                    body_message_rfc822.Message = message;
                }
                else
                {
                    MemoryStream ms = new MemoryStream();
                    message.Header.ToStream(ms, null, null);
                    ms.Position = 0;
                    body_message_rfc822.Message = Mail_Message.ParseFromStream(ms);
                }
                multipartReport.BodyParts.Add(entity_message_rfc822);
            }

            return(msg);
        }
Пример #16
0
 /// <summary>
 /// Default constructor.
 /// </summary>
 /// <param name="from">Sender email address. Value null means no sender info.</param>
 /// <param name="messageSize">Message size in bytes. Value -1 means that message size unknown.</param>
 /// <param name="ret">Delivery satus notification(DSN) RET value. For more info see RFC 3461.</param>
 /// <param name="envid">Delivery satus notification(DSN) ENVID value. Value null means not specified. For more info see RFC 3461.</param>
 /// <remarks>Before using <b>ret</b> or <b>envid</b> arguments, check that remote server supports(SMTP_Client.EsmtpFeatures) SMTP DSN extention.</remarks>
 public MailFromAsyncOP(string from,long messageSize,SMTP_DSN_Ret ret,string envid)
 {
     m_MailFrom    = from;
     m_MessageSize = messageSize;
     m_DsnRet      = ret;
     m_EnvID       = envid;
 }
Пример #17
0
        /// <summary>
        /// Sends MAIL FROM: command to SMTP server.
        /// </summary>
        /// <param name="from">Sender email address reported to SMTP server.</param>
        /// <param name="messageSize">Sendable message size in bytes, -1 if message size unknown.</param>
        /// <param name="ret">Delivery satus notification(DSN) RET value. For more info see RFC 3461.</param>
        /// <param name="envid">Delivery satus notification(DSN) ENVID value. Value null means not specified. For more info see RFC 3461.</param>
        /// <exception cref="ObjectDisposedException">Is raised when this object is disposed and this method is accessed.</exception>
        /// <exception cref="InvalidOperationException">Is raised when SMTP client is not connected.</exception>
        /// <exception cref="ArgumentException">Is raised when any of the arguments has invalid value.</exception>
        /// <exception cref="SMTP_ClientException">Is raised when SMTP server returns error.</exception>
        /// <remarks>Before using <b>ret</b> or <b>envid</b> arguments, check that remote server supports SMTP DSN extention.</remarks>
        public void MailFrom(string from,long messageSize,SMTP_DSN_Ret ret,string envid)
        {
            if(this.IsDisposed){
                throw new ObjectDisposedException(this.GetType().Name);
            }
            if(!this.IsConnected){
                throw new InvalidOperationException("You must connect first.");
            }
            if(!SMTP_Utils.IsValidAddress(from)){
                throw new ArgumentException("Argument from has invalid value.");
            }

            /* RFC 2821 4.1.1.2 MAIL
                Examples:
             		MAIL FROM:<*****@*****.**>

               RFC 1870 adds optional SIZE keyword support.
                SIZE keyword may only be used if it's reported in EHLO command response.
             	 Examples:
             		MAIL FROM:<*****@*****.**> SIZE=1000

               RFC 3461 adds RET and ENVID paramters.
            */

            bool isSizeSupported = false;
            foreach(string feature in m_pEsmtpFeatures){
                if(feature.ToLower() == "size"){
                    isSizeSupported = true;
                    break;
                }
            }

            StringBuilder cmd = new StringBuilder();
            cmd.Append("MAIL FROM:<" + from + ">");
            if(isSizeSupported && messageSize > 0){
                cmd.Append(" SIZE=" + messageSize.ToString());
            }
            if(ret == SMTP_DSN_Ret.FullMessage){
                cmd.Append(" RET=FULL");
            }
            else if(ret == SMTP_DSN_Ret.Headers){
                cmd.Append(" RET=HDRS");
            }
            if(!string.IsNullOrEmpty(envid)){
                cmd.Append(" ENVID=" + envid);
            }
            WriteLine(cmd.ToString());

            // Read first line of reply, check if it's ok.
            string line = ReadLine();
            if(!line.StartsWith("250")){
                throw new SMTP_ClientException(line);
            }

            m_MailFrom = from;
        }
Пример #18
0
        private void StoreRelayMessage(string queueName, string id, string envelopeID, DateTime date, Stream message, HostEndPoint targetHost, string sender, string to, string originalRecipient, SMTP_DSN_Notify notify, SMTP_DSN_Ret ret)
        {
            if (queueName == null)
            {
                throw new ArgumentNullException("queueName");
            }
            if (queueName == "")
            {
                throw new ArgumentException("Argumnet 'queueName' value must be specified.");
            }
            if (id == null)
            {
                throw new ArgumentNullException("id");
            }
            if (id == "")
            {
                throw new ArgumentException("Argument 'id' value must be specified.");
            }
            if (message == null)
            {
                throw new ArgumentNullException("message");
            }
            if (to == null)
            {
                throw new ArgumentNullException("to");
            }
            if (to == "")
            {
                throw new ArgumentException("Argument 'to' value must be specified.");
            }
            string text = this.m_pVirtualServer.MailStorePath + queueName;

            if (!Directory.Exists(text))
            {
                Directory.CreateDirectory(text);
            }
            using (FileStream fileStream = File.Create(PathHelper.PathFix(text + "\\" + id + ".eml")))
            {
                SCore.StreamCopy(message, fileStream);
                RelayMessageInfo relayMessageInfo = new RelayMessageInfo(envelopeID, sender, to, originalRecipient, notify, ret, date, false, targetHost);
                File.WriteAllBytes(PathHelper.PathFix(text + "\\" + id + ".info"), relayMessageInfo.ToByte());
            }
        }
Пример #19
0
        /// <summary>
        /// Sends MAIL command to SMTP server.
        /// </summary>
        /// <param name="from">Sender email address. Value null means no sender info.</param>
        /// <param name="messageSize">Message size in bytes. Value -1 means that message size unknown.</param>
        /// <param name="ret">Delivery satus notification(DSN) RET value. For more info see RFC 3461.</param>
        /// <param name="envid">Delivery satus notification(DSN) ENVID value. Value null means not specified. For more info see RFC 3461.</param>
        /// <exception cref="ObjectDisposedException">Is raised when this object is disposed and this method is accessed.</exception>
        /// <exception cref="InvalidOperationException">Is raised when SMTP client is not connected.</exception>
        /// <exception cref="ArgumentException">Is raised when any of the arguments has invalid value.</exception>
        /// <exception cref="SMTP_ClientException">Is raised when SMTP server returns error.</exception>
        /// <remarks>Before using <b>ret</b> or <b>envid</b> arguments, check that remote server supports(SMTP_Client.EsmtpFeatures) SMTP DSN extention.</remarks>
        public void MailFrom(string from,long messageSize,SMTP_DSN_Ret ret,string envid)
        {
            if(this.IsDisposed){
                throw new ObjectDisposedException(this.GetType().Name);
            }
            if(!this.IsConnected){
                throw new InvalidOperationException("You must connect first.");
            }
            
            ManualResetEvent wait = new ManualResetEvent(false);
            using(MailFromAsyncOP op = new MailFromAsyncOP(from,messageSize,ret,envid)){
                op.CompletedAsync += delegate(object s1,EventArgs<MailFromAsyncOP> e1){
                    wait.Set();
                };
                if(!this.MailFromAsync(op)){
                    wait.Set();
                }
                wait.WaitOne();
                wait.Close();

                if(op.Error != null){
                    throw op.Error;
                }
            }
        }
Пример #20
0
 /// <summary>
 /// Stores message for relay.
 /// </summary>
 /// <param name="id">Message ID. Guid value is suggested.</param>
 /// <param name="envelopeID">Envelope ID_(MAIL FROM: ENVID).</param>
 /// <param name="message">Message to store. Message will be readed from current position of stream.</param>
 /// <param name="targetHost">Target host or IP where to send message. This value can be null, then DNS MX o A record is used to deliver message.</param>
 /// <param name="sender">Sender address to report to target server.</param>
 /// <param name="to">Message recipient address.</param>
 /// <param name="originalRecipient">Original recipient(RCPT TO: ORCPT).</param>
 /// <param name="notify">DSN notify condition.</param>
 /// <param name="ret">Specifies what parts of message are returned in DSN report.</param>
 /// <exception cref="ArgumentNullException">Is raised when <b>id</b>,<b>message</b> or <b>to</b> is null.</exception>
 /// <exception cref="ArgumentException">Is raised when any of the argumnets has invalid value.</exception>
 public void StoreRelayMessage(string id,String envelopeID,Stream message,HostEndPoint targetHost,string sender,string to,string originalRecipient,SMTP_DSN_Notify notify,SMTP_DSN_Ret ret)
 {
     StoreRelayMessage("Relay",id,envelopeID,DateTime.Now,message,targetHost,sender,to,originalRecipient,notify,ret);
 }
Пример #21
0
        public IAsyncResult BeginMailFrom(string from,long messageSize,SMTP_DSN_Ret ret,string envid,AsyncCallback callback,object state)
        {
            if(this.IsDisposed){
                throw new ObjectDisposedException(this.GetType().Name);
            }
            if(!this.IsConnected){
				throw new InvalidOperationException("You must connect first.");
			}

            MailFromDelegate asyncMethod = new MailFromDelegate(this.MailFrom);
            AsyncResultState asyncState = new AsyncResultState(this,asyncMethod,callback,state);
            asyncState.SetAsyncResult(asyncMethod.BeginInvoke(from,(int)messageSize,ret,envid,new AsyncCallback(asyncState.CompletedCallback),null));

            return asyncState;
        }
Пример #22
0
        /// <summary>
        /// Processes and stores message.
        /// </summary>
        /// <param name="envelopeID">Envelope ID_(MAIL FROM: ENVID).</param>
        /// <param name="sender">Mail from.</param>
        /// <param name="ret">Specifies what parts of message are returned in DSN report.</param>
        /// <param name="recipients">Message recipients.</param>
        /// <param name="msgStream">Message stream. Stream position must be there where message begins.</param>
        /// <param name="e">Event data.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>recipients</b> or <b>msgStream</b> is nulll reference.</exception>
		public void ProcessAndStoreMessage(string envelopeID,string sender,SMTP_DSN_Ret ret,SMTP_RcptTo[] recipients,Stream msgStream,SMTP_e_MessageStored e)
		{
            if(recipients == null){
                throw new ArgumentNullException("recipients");
            }
            if(msgStream == null){
                throw new ArgumentNullException("msgStream");
            }

            /* Message processing.
                *) Message filters.
                *) Global message rules.
                *) Process recipients.
            */

            List<SMTP_RcptTo> dsn_Delivered = new List<SMTP_RcptTo>();

            string[] to = new string[recipients.Length];
            for(int i=0;i<to.Length;i++){
                to[i] = recipients[i].Mailbox;
            }
         
			#region Global Filtering stuff
            
			//--- Filter message -----------------------------------------------//
			Stream filteredMsgStream = msgStream;
			DataView dvFilters = m_pApi.GetFilters();
			dvFilters.RowFilter = "Enabled=true AND Type='ISmtpMessageFilter'";
			dvFilters.Sort = "Cost";			
			foreach(DataRowView drViewFilter in dvFilters){
                try{
				    filteredMsgStream.Position = 0;

				    string assemblyFile = API_Utlis.PathFix(drViewFilter.Row["Assembly"].ToString());
				    // File is without path probably, try to load it from filters folder
				    if(!File.Exists(assemblyFile)){
					    assemblyFile = API_Utlis.PathFix(m_pOwnerServer.StartupPath + "\\Filters\\" + assemblyFile);
				    }

				    Assembly ass = Assembly.LoadFrom(assemblyFile);
				    Type tp = ass.GetType(drViewFilter.Row["ClassName"].ToString());
				    object filterInstance = Activator.CreateInstance(tp);
				    ISmtpMessageFilter filter = (ISmtpMessageFilter)filterInstance;
    						
				    string errorText = "";
                    SMTP_Session session = null;
                    if(e != null){
                        session = e.Session;
                    }
				    FilterResult result = filter.Filter(filteredMsgStream,out filteredMsgStream,sender,to,m_pApi,session,out errorText);
                    if(result == FilterResult.DontStore){
                        // Just skip messge, act as message is stored
                        e.Reply = new SMTP_Reply(552,"Requested mail action aborted: Message discarded by server filter.");
						return; 
                    }
                    else if(result == FilterResult.Error){
                        if(e != null){
                            e.Reply = new SMTP_Reply(552,"Requested mail action aborted: " + errorText);
                        }
                        else{
                            // NOTE: 26.01.2006 - e maybe null if that method is called server internally and no smtp session.                            
                        }
						return;
                    }
                    
                    // Filter didn't return message stream
                    if(filteredMsgStream == null){
				        e.Reply = new SMTP_Reply(552,"Requested mail action aborted: Message discarded by server filter.");
                        return;
                    }
                }
                catch(Exception x){
                    // Filtering failed, log error and allow message through.
                    OnError(x);
                }
			}
			//---------------------------------------------------------------//
			#endregion

            #region Global Message Rules
  
            filteredMsgStream.Position = 0;
                         
            Mail_Message mime = null;
            try{
                mime = Mail_Message.ParseFromStream(filteredMsgStream);
            }
            // Invalid message syntax, block such message.
            catch{
                e.Reply = new SMTP_Reply(552,"Requested mail action aborted: Message has invalid structure/syntax.");
                               
                try{
                    if(!Directory.Exists(this.MailStorePath + "Unparseable")){
                        Directory.CreateDirectory(this.MailStorePath + "Unparseable");
                    }
                                
                    using(FileStream fs = File.Create(this.MailStorePath + "Unparseable\\" + Guid.NewGuid().ToString().Replace("-","") + ".eml")){
                        filteredMsgStream.Position = 0;
                        Net_Utils.StreamCopy(filteredMsgStream,fs,32000);
                    }
                }
                catch{
                }

                return;
            }

            //--- Check Global Message Rules --------------------------------------------------------------//
            bool   deleteMessage = false;
            string storeFolder   = "Inbox";
            string smtpErrorText = null;   

            // Loop rules
            foreach(DataRowView drV_Rule in m_pApi.GetGlobalMessageRules()){
                // Reset stream position
                filteredMsgStream.Position = 0;

                if(Convert.ToBoolean(drV_Rule["Enabled"])){
                    string ruleID = drV_Rule["RuleID"].ToString();
                    GlobalMessageRule_CheckNextRule_enum checkNextIf = (GlobalMessageRule_CheckNextRule_enum)(int)drV_Rule["CheckNextRuleIf"];
                    string matchExpression = drV_Rule["MatchExpression"].ToString();

                    // e may be null if server internal method call and no actual session !
                    SMTP_Session session = null;
                    if(e != null){
                        session = e.Session;
                    }
                    GlobalMessageRuleProcessor ruleEngine = new GlobalMessageRuleProcessor();
                    bool matches = ruleEngine.Match(matchExpression,sender,to,session,mime,(int)filteredMsgStream.Length);
                    if(matches){                        
                        // Do actions
                        GlobalMessageRuleActionResult result = ruleEngine.DoActions(
                            m_pApi.GetGlobalMessageRuleActions(ruleID),
                            this,
                            filteredMsgStream,
                            sender,
                            to
                        );

                        if(result.DeleteMessage){
                            deleteMessage = true;
                        }
                        if(result.StoreFolder != null){                            
                            storeFolder = result.StoreFolder;                           
                        }
                        if(result.ErrorText != null){
                            smtpErrorText = result.ErrorText;
                        }
                    }

                    //--- See if we must check next rule -------------------------------------------------//
                    if(checkNextIf == GlobalMessageRule_CheckNextRule_enum.Always){
                        // Do nothing
                    }
                    else if(checkNextIf == GlobalMessageRule_CheckNextRule_enum.IfMatches && !matches){
                        break;
                    }
                    else if(checkNextIf == GlobalMessageRule_CheckNextRule_enum.IfNotMatches && matches){
                        break;
                    }
                    //------------------------------------------------------------------------------------//
                }
            }

            // Return error to connected client
            if(smtpErrorText != null){
                e.Reply = new SMTP_Reply(552,"Requested mail action aborted: " + smtpErrorText);
                return;
            }

            // Just don't store message
            if(deleteMessage){
                return;
            }
            
            // Reset stream position
            filteredMsgStream.Position = 0;
            //--- End of Global Rules -------------------------------------------------------------------//

            #endregion
            
            #region Process recipients
                  
            HashSet<string> processedItems = new HashSet<string>();

            Queue<SMTP_RcptTo> recipientsQueue = new Queue<SMTP_RcptTo>();
            // Queue current recipients for processing.
            foreach(SMTP_RcptTo recipient in recipients){
                recipientsQueue.Enqueue(recipient);
            }

            while(recipientsQueue.Count > 0){
                /* Process order
                    *) Local user
                    *) Local address
                    *) Local mailing list address
                    *) Route
                    *) Relay
                */

                SMTP_RcptTo recipient = recipientsQueue.Dequeue();

                // Check if we already have processed this item. Skip dublicate items.
                // This method also avoids loops when 2 recipients reference each other.
                if(processedItems.Contains(recipient.Mailbox)){
                    continue;
                }
                processedItems.Add(recipient.Mailbox);
                               

                #region Local user

                if(recipient.Mailbox.IndexOf('@') == -1 && m_pApi.UserExists(recipient.Mailbox)){
                    // Add user to processed list.
                    processedItems.Add(recipient.Mailbox);

                    // Delivery status notification(DSN) requested to this user.
                    if((recipient.Notify & SMTP_DSN_Notify.Success) != 0){
                        dsn_Delivered.Add(recipient);
                    }

                    ProcessUserMsg(sender,recipient.Mailbox,recipient.Mailbox,storeFolder,filteredMsgStream,e);

                    continue;
                }

                #endregion

                #region Local address

                string localUser = m_pApi.MapUser(recipient.Mailbox);
                if(localUser != null){
                    // Add user to processed list.
                    processedItems.Add(localUser);

                    // Delivery status notification(DSN) requested to this user.
                    if((recipient.Notify & SMTP_DSN_Notify.Success) != 0){
                        dsn_Delivered.Add(recipient);
                    }

                    ProcessUserMsg(sender,recipient.Mailbox,localUser,storeFolder,filteredMsgStream,e);
                }

                #endregion

                #region Mailing list address

                else if(m_pApi.MailingListExists(recipient.Mailbox)){
                    // Delivery status notification(DSN) requested to this user.
                    if((recipient.Notify & SMTP_DSN_Notify.Success) != 0){
                        dsn_Delivered.Add(recipient);
                    }

                    Queue<string> processQueue = new Queue<string>();
                    processQueue.Enqueue(recipient.Mailbox);

                    // Loop while there are mailing lists or nested mailing list available
                    while(processQueue.Count > 0){
                        string mailingList = processQueue.Dequeue(); 
                          
                        // Process mailing list members
					    foreach(DataRowView drV in m_pApi.GetMailingListAddresses(mailingList)){
                            string member = drV["Address"].ToString();

                            // Member is asteric pattern matching server emails
                            if(member.IndexOf('*') > -1){
                                DataView dvServerAddresses = m_pApi.GetUserAddresses("");
                                foreach(DataRowView drvServerAddress in dvServerAddresses){
                                    string serverAddress = drvServerAddress["Address"].ToString();
                                    if(SCore.IsAstericMatch(member,serverAddress)){
                                        recipientsQueue.Enqueue(new SMTP_RcptTo(serverAddress,SMTP_DSN_Notify.NotSpecified,null));                                        
                                    }
                                }
                            }
                            // Member is user or group, not email address
                            else if(member.IndexOf('@') == -1){                            
                                // Member is group, replace with actual users
                                if(m_pApi.GroupExists(member)){
                                    foreach(string user in m_pApi.GetGroupUsers(member)){
                                        recipientsQueue.Enqueue(new SMTP_RcptTo(user,SMTP_DSN_Notify.NotSpecified,null));                                        
                                    }
                                }
                                // Member is user
                                else if(m_pApi.UserExists(member)){
                                    recipientsQueue.Enqueue(new SMTP_RcptTo(member,SMTP_DSN_Notify.NotSpecified,null));                                    
                                }
                                // Unknown member, skip it.
                                else{
                                }
                            }
                            // Member is nested mailing list
                            else if(m_pApi.MailingListExists(member)){
                                processQueue.Enqueue(member);                                
                            }
                            // Member is normal email address
                            else{
                                recipientsQueue.Enqueue(new SMTP_RcptTo(member,SMTP_DSN_Notify.NotSpecified,null));                                
                            }					
					    }
                    }
                }

                #endregion

                else{
                    bool isRouted = false;

                    #region Check Routing

                    foreach(DataRowView drRoute in m_pApi.GetRoutes()){
                        // We have matching route
                        if(Convert.ToBoolean(drRoute["Enabled"]) && SCore.IsAstericMatch(drRoute["Pattern"].ToString(),recipient.Mailbox)){
                            string           description = drRoute["Action"].ToString();    
                            RouteAction_enum action      = (RouteAction_enum)Convert.ToInt32(drRoute["Action"]);
                            byte[]           actionData  = (byte[])drRoute["ActionData"];

                            #region RouteToEmail

                            if(action == RouteAction_enum.RouteToEmail){
                                XmlTable table = new XmlTable("ActionData");
                                table.Parse(actionData);

                                // Add email to process queue.
                                recipientsQueue.Enqueue(new SMTP_RcptTo(table.GetValue("EmailAddress"),SMTP_DSN_Notify.NotSpecified,null));

                                // Log
                                if(e != null){
                                    e.Session.LogAddText("Route '[" + description + "]: " + drRoute["Pattern"].ToString() + "' routed to email '" + table.GetValue("EmailAddress") + "'.");
                                }
                            }

                            #endregion

                            #region RouteToHost

                            else if(action == RouteAction_enum.RouteToHost){
                                XmlTable table = new XmlTable("ActionData");
                                table.Parse(actionData);  

                                msgStream.Position = 0;

                                // Route didn't match, so we have relay message.
                                this.RelayServer.StoreRelayMessage(                    
                                    Guid.NewGuid().ToString(),
                                    envelopeID,
                                    msgStream,
                                    HostEndPoint.Parse(table.GetValue("Host") + ":" + table.GetValue("Port")),
                                    sender,
                                    recipient.Mailbox,
                                    recipient.ORCPT,
                                    recipient.Notify,
                                    ret
                                );
                             
                                // Log
                                if(e != null){
                                    e.Session.LogAddText("Route '[" + description + "]: " + drRoute["Pattern"].ToString() + "' routed to host '" + table.GetValue("Host") + ":" + table.GetValue("Port") + "'.");
                                }
                            }

                            #endregion

                            #region RouteToMailbox

                            else if(action == RouteAction_enum.RouteToMailbox){
                                XmlTable table = new XmlTable("ActionData");
                                table.Parse(actionData);

                                ProcessUserMsg(sender,recipient.Mailbox,table.GetValue("Mailbox"),storeFolder,filteredMsgStream,e);

                                // Log
                                if(e != null){
                                    e.Session.LogAddText("Route '[" + description + "]: " + drRoute["Pattern"].ToString() + "' routed to user '" + table.GetValue("Mailbox") + "'.");
                                }
                            }

                            #endregion
                             
                            isRouted = true;
                            break;
                        }
                    }

                   #endregion

                    // Route didn't match, so we have relay message.
                    if(!isRouted){
                        filteredMsgStream.Position = 0;

                        this.RelayServer.StoreRelayMessage(                    
                            Guid.NewGuid().ToString(),
                            envelopeID,
                            filteredMsgStream,
                            null,
                            sender,
                            recipient.Mailbox,
                            recipient.ORCPT,
                            recipient.Notify,
                            ret
                        );
                    }
                }
            }

            #endregion

            
            #region DSN "delivered"

            // Send DSN for requested recipients.
            if(dsn_Delivered.Count > 0 && !string.IsNullOrEmpty(sender)){
                try{
                    string dsn_to = "";
                    for(int i=0;i<dsn_Delivered.Count;i++){
                        if(i == (dsn_Delivered.Count - 1)){
                            dsn_to += dsn_Delivered[i].Mailbox;
                        }
                        else{
                            dsn_to += dsn_Delivered[i].Mailbox + "; ";
                        }
                    }

                    string reportingMTA = "";
                    if(e != null && !string.IsNullOrEmpty(e.Session.LocalHostName)){
                        reportingMTA = e.Session.LocalHostName;
                    }
                    else{
                        reportingMTA = System.Net.Dns.GetHostName();
                    }

                    ServerReturnMessage messageTemplate = null;
                    if(messageTemplate == null){
                        string bodyRtf = "" +
                        "{\\rtf1\\ansi\\ansicpg1257\\deff0\\deflang1061{\\fonttbl{\\f0\\froman\\fcharset0 Times New Roman;}{\\f1\froman\\fcharset186{\\*\\fname Times New Roman;}Times New Roman Baltic;}{\\f2\fswiss\\fcharset186{\\*\\fname Arial;}Arial Baltic;}}\r\n" +
                        "{\\colortbl ;\\red0\\green128\\blue0;\\red128\\green128\\blue128;}\r\n" +
                        "{\\*\\generator Msftedit 5.41.21.2508;}\\viewkind4\\uc1\\pard\\sb100\\sa100\\lang1033\\f0\\fs24\\par\r\n" +
                        "Your message WAS SUCCESSFULLY DELIVERED to:\\line\\lang1061\\f1\\tab\\cf1\\lang1033\\b\\f0 " + dsn_to + "\\line\\cf0\\b0 and you explicitly requested a delivery status notification on success.\\par\\par\r\n" +
                        "\\cf2 Your original message\\lang1061\\f1 /header\\lang1033\\f0  is attached to this e-mail\\lang1061\\f1 .\\lang1033\\f0\\par\\r\\n" +
                        "\\cf0\\line\\par\r\n" +
                        "\\pard\\lang1061\\f2\\fs20\\par\r\n" +
                        "}\r\n";

                        messageTemplate = new ServerReturnMessage("DSN SUCCESSFULLY DELIVERED: " + mime.Subject,bodyRtf);
                    }

                    string rtf = messageTemplate.BodyTextRtf;

                    Mail_Message dsnMsg = new Mail_Message();
                    dsnMsg.MimeVersion = "1.0";
                    dsnMsg.Date = DateTime.Now;
                    dsnMsg.From = new Mail_t_MailboxList();
                    dsnMsg.From.Add(new Mail_t_Mailbox("Mail Delivery Subsystem","postmaster@local"));
                    dsnMsg.To = new Mail_t_AddressList();
                    dsnMsg.To.Add(new Mail_t_Mailbox(null,sender));
                    dsnMsg.Subject = messageTemplate.Subject;

                    //--- multipart/report -------------------------------------------------------------------------------------------------
                    MIME_h_ContentType contentType_multipartReport = new MIME_h_ContentType(MIME_MediaTypes.Multipart.report);            
                    contentType_multipartReport.Parameters["report-type"] = "delivery-status";
                    contentType_multipartReport.Param_Boundary = Guid.NewGuid().ToString().Replace('-','.');
                    MIME_b_MultipartReport multipartReport = new MIME_b_MultipartReport(contentType_multipartReport);
                    dsnMsg.Body = multipartReport;

                        //--- multipart/alternative -----------------------------------------------------------------------------------------
                        MIME_Entity entity_multipart_alternative = new MIME_Entity();
                        MIME_h_ContentType contentType_multipartAlternative = new MIME_h_ContentType(MIME_MediaTypes.Multipart.alternative);
                        contentType_multipartAlternative.Param_Boundary = Guid.NewGuid().ToString().Replace('-','.');
                        MIME_b_MultipartAlternative multipartAlternative = new MIME_b_MultipartAlternative(contentType_multipartAlternative);
                        entity_multipart_alternative.Body = multipartAlternative;
                        multipartReport.BodyParts.Add(entity_multipart_alternative);

                            //--- text/plain ---------------------------------------------------------------------------------------------------
                            MIME_Entity entity_text_plain = new MIME_Entity();
                            MIME_b_Text text_plain = new MIME_b_Text(MIME_MediaTypes.Text.plain);
                            entity_text_plain.Body = text_plain;
                            text_plain.SetText(MIME_TransferEncodings.QuotedPrintable,Encoding.UTF8,SCore.RtfToText(rtf));
                            multipartAlternative.BodyParts.Add(entity_text_plain);

                            //--- text/html -----------------------------------------------------------------------------------------------------
                            MIME_Entity entity_text_html = new MIME_Entity();
                            MIME_b_Text text_html = new MIME_b_Text(MIME_MediaTypes.Text.html);
                            entity_text_html.Body = text_html;
                            text_html.SetText(MIME_TransferEncodings.QuotedPrintable,Encoding.UTF8,SCore.RtfToHtml(rtf));
                            multipartAlternative.BodyParts.Add(entity_text_html);

                        //--- message/delivery-status
                        MIME_Entity entity_message_deliveryStatus = new MIME_Entity();                        
                        MIME_b_MessageDeliveryStatus body_message_deliveryStatus = new MIME_b_MessageDeliveryStatus();
                        entity_message_deliveryStatus.Body = body_message_deliveryStatus;
                        multipartReport.BodyParts.Add(entity_message_deliveryStatus);
            
                        //--- per-message-fields ----------------------------------------------------------------------------
                        MIME_h_Collection messageFields = body_message_deliveryStatus.MessageFields;
                        if(!string.IsNullOrEmpty(envelopeID)){
                            messageFields.Add(new MIME_h_Unstructured("Original-Envelope-Id",envelopeID));
                        }
                        messageFields.Add(new MIME_h_Unstructured("Arrival-Date",MIME_Utils.DateTimeToRfc2822(DateTime.Now)));
                        if(e != null && !string.IsNullOrEmpty(e.Session.EhloHost)){
                            messageFields.Add(new MIME_h_Unstructured("Received-From-MTA","dns;" + e.Session.EhloHost));
                        }
                        messageFields.Add(new MIME_h_Unstructured("Reporting-MTA","dns;" + reportingMTA));
                        //---------------------------------------------------------------------------------------------------

                        foreach(SMTP_RcptTo r in dsn_Delivered){
                            //--- per-recipient-fields --------------------------------------------------------------------------
                            MIME_h_Collection recipientFields = new MIME_h_Collection(new MIME_h_Provider());
                            if(r.ORCPT != null){
                                recipientFields.Add(new MIME_h_Unstructured("Original-Recipient",r.ORCPT));
                            }
                            recipientFields.Add(new MIME_h_Unstructured("Final-Recipient","rfc822;" + r.Mailbox));
                            recipientFields.Add(new MIME_h_Unstructured("Action","delivered"));
                            recipientFields.Add(new MIME_h_Unstructured("Status","2.0.0"));
                            body_message_deliveryStatus.RecipientBlocks.Add(recipientFields);
                            //---------------------------------------------------------------------------------------------------
                        }
                                            
                        //--- message/rfc822
                        if(mime != null){
                            MIME_Entity entity_message_rfc822 = new MIME_Entity();
                            MIME_b_MessageRfc822 body_message_rfc822 = new MIME_b_MessageRfc822();
                            entity_message_rfc822.Body = body_message_rfc822;
                            if(ret == SMTP_DSN_Ret.FullMessage){
                                body_message_rfc822.Message = mime;
                            }
                            else{
                                MemoryStream ms = new MemoryStream();
                                mime.Header.ToStream(ms,null,null);
                                ms.Position = 0;
                                body_message_rfc822.Message = Mail_Message.ParseFromStream(ms);
                            }
                            multipartReport.BodyParts.Add(entity_message_rfc822);
                        }

                    using(MemoryStream strm = new MemoryStream()){
					    dsnMsg.ToStream(strm,new MIME_Encoding_EncodedWord(MIME_EncodedWordEncoding.Q,Encoding.UTF8),Encoding.UTF8);
					    ProcessAndStoreMessage("",new string[]{sender},strm,null);
				    }
                }
                catch(Exception x){
                    Error.DumpError(this.Name,x);
                }
            }

            #endregion
        }