/// <summary>
        /// To simplify inbound mail sending, SMTP Server allows you to drop new messages into a pickup folder
        /// You don't need to use SmtpClient or some other SMTP client
        /// </summary>
        public void SendFailure(OutgoingMessage envelope, string pickupFolder, DirectAddressCollection recipients) 
        {
            if (string.IsNullOrEmpty(pickupFolder))
            {
                throw new ArgumentException("value null or empty", "pickupFolder");
            }

            if (recipients.IsNullOrEmpty())
            {
                return;
            }

            if (recipients != null && envelope.UsingDeliveryStatus)
            {
                DSNMessage notification = this.ProduceFailure(envelope, recipients);
                           

                string filePath = Path.Combine(pickupFolder, Extensions.CreateUniqueFileName());
                notification.Save(filePath);
            }
            

            //Or maybe
            //
            // m_router.Route(message, envelope, routedRecipients);  
            // 
            // This would avoid loopback encrypt/decrypt...
            //
            // ISmtpMessage message
            // MessageEnvelope envelope 
            // DirectAddressCollection routedRecipients, but would use DSN in-reply-to:
            //
            
            
        }
 // extract into MdnMonitorParser
 private static List<Mdn> CreateMdnStarts(OutgoingMessage message)
 {
     return message.Recipients.Select(
         recipient => new Mdn(message.Message.IDValue
             , new MailAddress(recipient.Address).Address
             , new MailAddress(message.NotifyTo.ToString()).Address
             , message.IsTimelyAndReliable.GetValueOrDefault(false))
         ).ToList();
 }
        internal void StartMdn(OutgoingMessage message)
        {
            Debug.Assert(m_settings.HasMdnManager);

            using (MdnMonitorClient client = m_settings.MdnMonitor.CreateMdnMonitorClient())
            {
                List<Mdn> mdns = CreateMdnStarts(message);
                client.Start(mdns.ToArray());
            }
        }
示例#4
0
 internal void OnOutgoingError(OutgoingMessage message, Exception error)
 {
     if (Logger.IsDebugEnabled)
     {
         Logger.Error(this.BuildVerboseErrorMessage("OUTGOING", message, error));
     }
     else
     {
         Logger.Error("OUTGOING_ERROR {0}", error.Message);
     }
 }
示例#5
0
        /// <summary>
        /// To simplify inbound mail sending, SMTP Server allows you to drop new messages into a pickup folder
        /// You don't need to use SmtpClient or some other SMTP client
        /// </summary>
        public void SendFailure(OutgoingMessage envelope, string pickupFolder) 
        {
            if (string.IsNullOrEmpty(pickupFolder))
            {
                throw new ArgumentException("value null or empty", "pickupFolder");
            }

            DirectAddressCollection recipients = envelope.RejectedRecipients;

            if (recipients.IsNullOrEmpty())
            {
                return;
            }

            if (recipients != null && envelope.UsingDeliveryStatus)
            {
                DSNMessage notification = this.ProduceFailure(envelope, recipients);


                string filePath = Path.Combine(pickupFolder, Extensions.CreateUniqueFileName());
                notification.Save(filePath);
            }
            
        }
示例#6
0
        //-------------------------------------------------------------------
        //
        // OUTGOING MESSAGE
        //
        //------------------------------------------------------------------- 
		
        /// <summary> 
        /// Encrypts, verifies recipient trust, and signs an RFC 5322 formatted message 
        /// </summary> 
        /// <param name="messageText"> 
        /// An RFC 5322 formatted message string 
        /// </param> 
        /// <returns> 
        /// An <see cref="OutgoingMessage"/> instance containing the encrypted and trust verified message. 
        /// </returns> 
        public OutgoingMessage ProcessOutgoing(string messageText)
        {
            if (string.IsNullOrEmpty(messageText))
            {
                throw new ArgumentException("value was null or empty", "messageText");
            }

            OutgoingMessage message = new OutgoingMessage(this.WrapMessage(messageText));
            
            return this.ProcessOutgoing(message);
        }
        /// <summary>
        /// Generate internal notification messages (if any) for this outgoing message
        /// </summary>
        /// <param name="envelope"></param>
        /// <param name="recipients">sending failure status for these message recipients</param>
        /// <returns>An DSNmessage</returns>
        public DSNMessage ProduceFailure(OutgoingMessage envelope, DirectAddressCollection recipients)
        {
            if (envelope == null)
            {
                throw new ArgumentNullException("envelope");
            }

            if (string.IsNullOrEmpty(m_settings.ProductName))
            {
                throw new ArgumentException("reportingAgentName:AgentSettings:ProductName");
            }

            DSNPerMessage perMessage = new DSNPerMessage(envelope.Sender.Host, envelope.Message.IDValue);

            //
            // Un-Secured recipients
            //
            List<DSNPerRecipient> dsnPerRecipients = envelope.CreatePerRecipientStatus(recipients.UnResolvedCertificates().AsMailAddresses()
                , m_settings.Text, m_settings.AlwaysAck, DSNStandard.DSNAction.Failed, DSNStandard.DSNStatus.Permanent
                , DSNStandard.DSNStatus.UNSECURED_STATUS).ToList();
            //
            // Un-Trusted recipients
            //
            dsnPerRecipients.AddRange(envelope.CreatePerRecipientStatus(recipients.ResolvedCertificates().AsMailAddresses()
                , m_settings.Text, m_settings.AlwaysAck, DSNStandard.DSNAction.Failed, DSNStandard.DSNStatus.Permanent
                , DSNStandard.DSNStatus.UNTRUSTED_STATUS).ToList());

            DSN dsn = new DSN(perMessage, dsnPerRecipients);

            //Configure and/or dynamic plus refactor
            return envelope.Message.CreateStatusMessage(new MailAddress("Postmaster@" + envelope.Sender.Host), dsn);

        }
示例#8
0
 void Notify(OutgoingMessage message, Action<OutgoingMessage> eventHandler)
 {
     //
     // exceptions are interpreted as: abort message
     //
     if (eventHandler != null)
     {
         eventHandler(message);
     }
 }
示例#9
0
        //
        // First sign, THEN encrypt the message
        //
        void SignAndEncryptMessage(OutgoingMessage message)
        {
            SignedEntity signedEntity = m_cryptographer.Sign(message.Message, message.Sender.Certificates);

            if (m_encryptionEnabled)
            {
                //
                // Encrypt the outbound message with all known trusted certs
                //
                MimeEntity encryptedEntity = m_cryptographer.Encrypt(signedEntity, message.Recipients.GetCertificates());
                //
                // Alter message content to contain encrypted data
                //
                message.Message.UpdateBody(encryptedEntity);
            }
            else
            {
                message.Message.UpdateBody(signedEntity);
            }
        }
示例#10
0
 void BindAddresses(OutgoingMessage message)
 {
     //
     // Retrieving the sender's private certificate is requied for encryption
     //
     if (message.UseIncomingTrustAnchors)
     {
         message.Sender.TrustAnchors = m_trustAnchors.IncomingAnchors.GetCertificates(message.Sender);
     }
     else
     {
         message.Sender.TrustAnchors = m_trustAnchors.OutgoingAnchors.GetCertificates(message.Sender);
     }
     message.Sender.Certificates = this.ResolvePrivateCerts(message.Sender, true);
     //
     // Bind each recipient's certs
     //
     DirectAddressCollection recipients = message.Recipients;
     for (int i = 0, count = recipients.Count; i < count; ++i)
     {
         DirectAddress recipient = recipients[i];
         X509Certificate2Collection certificates = this.ResolvePublicCerts(recipient, false);
         recipient.Certificates = certificates;
         if(certificates != null)
         {
             recipient.ResolvedCertificates = true;
         }
     }
 }
示例#11
0
 void ProcessMessage(OutgoingMessage message)
 {
     if (!WrappedMessage.IsWrapped(message.Message))
     {
         message.Message = message.HasRawMessage ? this.WrapMessage(message.RawMessage) : this.WrapMessage(message.Message);
     }
     
     if (message.Sender == null)
     {
         throw new OutgoingAgentException(AgentError.NoSender);
     }            
     if (!message.HasRecipients)
     {
         throw new OutgoingAgentException(AgentError.NoRecipients);
     }
     //
     // Ensure we support this sender's domain
     //
     if (!m_managedDomains.IsManaged(message.Sender))
     {
         throw new OutgoingAgentException(AgentError.UntrustedSender);
     }
     //
     // Categorize recipients as local/external
     //
     message.EnsureRecipientsCategorizedByDomain(m_managedDomains);
     //
     // Bind addresses to Certs etc
     //
     this.BindAddresses(message);
     if (!message.HasRecipients)
     {
         throw new OutgoingAgentException(AgentError.MissingTo);
     }            
     //
     // Enforce the trust model.
     //
     m_trustModel.Enforce(message);
     //
     // Remove any non-trusted recipients
     //
     message.CategorizeRecipientsByTrust(m_minTrustRequirement);
     if (!message.HasRecipients)
     {
         throw new OutgoingAgentException(AgentError.NoTrustedRecipients);
     }
     //
     // And update routing headers to remove any recipients we had yanked
     //
     message.UpdateRoutingHeaders();
     //
     // Finally, sign and encrypt the message
     //
     this.SignAndEncryptMessage(message);
 }
示例#12
0
        /// <summary>
        /// Encrypts, verifies recipient trust, and signs an OutgoingMessage containing a message to prepare for send.
        /// </summary>
        /// <param name="message">
        /// An <see cref="OutgoingMessage"/> instance containing the message to prepare for send.
        /// </param>
        /// <returns>
        /// An <see cref="OutgoingMessage"/> instance containing the encrypted and trust verified message.
        /// </returns>
        public OutgoingMessage ProcessOutgoing(OutgoingMessage message)
        {
            if (message == null)
            {
                throw new ArgumentNullException("message");
            }

            try
            {
                message.Validate();

                this.Notify(message, this.PreProcessOutgoing);

                this.ProcessMessage(message);

                this.Notify(message, this.PostProcessOutgoing);
            }
            catch (Exception error)
            {
                this.Notify(message, error);
                throw;
            }
            
            return message;
        }
示例#13
0
        //---------------------------------------------------
        //
        //  Outgoing
        //
        //---------------------------------------------------

        void OnPreProcessOutgoing(OutgoingMessage message)
        {
            if (m_settings.HasAddressManager)
            {
                VerifySenderAddress(message);
            }
        }
示例#14
0
 void Notify(OutgoingMessage message, Exception ex)
 {
     try
     {
         Action<OutgoingMessage, Exception> errorOutgoing = ErrorOutgoing;
         if (errorOutgoing != null)
         {
             errorOutgoing(message, ex);
         }
     }
     catch
     {
     }
 }
示例#15
0
        /// <summary>
        /// Encrypts, verifies recipient trust, and signs an RFC 5322 formatted message
        /// The provided sender and recipient addresses will be used instead of the header information in the <c>messageText</c>.
        /// </summary>
        /// <param name="messageText">
        /// An RFC 5322 formatted message string
        /// </param>
        /// <param name="recipients">
        /// An <see cref="DirectAddressCollection"/> instance specifying message recipients.
        /// </param>
        /// <param name="sender">
        /// An <see cref="DirectAddress"/> instance specifying message sender
        /// </param>
        /// <returns>
        /// An <see cref="OutgoingMessage"/> instance containing the encrypted and trust verified message.
        /// </returns>
        public OutgoingMessage ProcessOutgoing(string messageText, DirectAddressCollection recipients, DirectAddress sender)
        {
            OutgoingMessage message = new OutgoingMessage(this.WrapMessage(messageText), recipients, sender);

            return(this.ProcessOutgoing(message));
        }
示例#16
0
        void SendDeliveryStatus(OutgoingMessage envelope)
        {
            if (!m_settings.InternalMessage.HasPickupFolder)
            {
                return;
            }
            //
            // Its ok if we fail on sending un-secured notifications - that should never cause us to not
            // deliver the message
            //
            try
            {
                bool isMdnSet = envelope.IsMDN.GetValueOrDefault(false);
                if (isMdnSet || !envelope.HasRejectedRecipients)
                {
                    return;
                }
                m_notifications.SendFailure(envelope, m_settings.InternalMessage.PickupFolder);
            }
            catch (Exception ex)
            {
                Logger.Error("While sending un-secured DSN {0}", ex.Message);
                Logger.Debug(ex.ToString());
            }     

        }
示例#17
0
        void PostProcessOutgoing(ISmtpMessage message, OutgoingMessage envelope)
        {
            MonitorMdn(envelope);

            SendDeliveryStatus(envelope);

            this.RelayInternal(message, envelope); //Removes recipients in local domains
            
            if (envelope.HasRecipients)
            {            
                this.CopyMessage(message, m_settings.Outgoing);
            }
            
            if (m_settings.Outgoing.EnableRelay && envelope.HasRecipients)
            {
                message.SetRcptTo(envelope.Recipients);
                m_diagnostics.LogEnvelopeHeaders(message);
            }
            else
            {
                message.Abort();
            }
        }
示例#18
0
        protected virtual MessageEnvelope ProcessOutgoing(ISmtpMessage message, MessageEnvelope envelope)
        {
            OutgoingMessage outgoing = new OutgoingMessage(envelope);
            
            if (envelope.Message.IsMDN())
            {
                outgoing.IsMDN = true;
                outgoing.UseIncomingTrustAnchors = this.Settings.Notifications.UseIncomingTrustAnchorsToSend;
            }

            if (envelope.Message.IsDSN())
            {
                outgoing.IsDSN = true;
                outgoing.UseIncomingTrustAnchors = this.Settings.Notifications.UseIncomingTrustAnchorsToSend;
            }
            
            if (envelope.Message.IsTimelyAndReliable())
            {
                outgoing.IsTimelyAndReliable = true;
            }

            outgoing.UsingDeliveryStatus = outgoing.ShouldDeliverFailedStatus(Settings.Notifications);

            envelope = this.SecurityAgent.ProcessOutgoing(outgoing);
            Logger.Debug("ProcessedOutgoing"); 
            return envelope;
        }
示例#19
0
 void MonitorMdn(OutgoingMessage outgoingMessage)
 {
     bool isMdnSet = outgoingMessage.IsMDN.GetValueOrDefault(false);
     bool isDsnSet = outgoingMessage.IsDSN.GetValueOrDefault(false);
     if (m_settings.HasMdnManager && !isMdnSet && !isDsnSet)
     {
         m_monitorService.StartMdn(outgoingMessage);
     }
 }
示例#20
0
        //
        // Verify that the sender is allowed to send
        //
        private void VerifySenderAddress(OutgoingMessage message)
        {
            Address address = m_configService.GetAddress(message.Sender);
            if (address == null)
            {
                throw new AgentException(AgentError.UntrustedSender);
            }

            message.Sender.Tag = address;
        }
示例#21
0
 internal void ProcessEndToEnd(SmtpAgent agent, Message msg, out OutgoingMessage outgoing, out IncomingMessage incoming)
 {
     outgoing = agent.SecurityAgent.ProcessOutgoing(new MessageEnvelope(msg));
     incoming = agent.SecurityAgent.ProcessIncoming(new MessageEnvelope(outgoing.SerializeMessage()));            
 }
示例#22
0
 /// <summary>
 /// Encrypts, verifies recipient trust, and signs an RFC 5322 formatted message 
 /// The provided sender and recipient addresses will be used instead of the header information in the <c>messageText</c>. 
 /// </summary>
 /// <param name="messageText">
 /// An RFC 5322 formatted message string 
 /// </param>
 /// <param name="recipients">
 /// An <see cref="DirectAddressCollection"/> instance specifying message recipients.
 /// </param>
 /// <param name="sender">
 /// An <see cref="DirectAddress"/> instance specifying message sender
 /// </param>
 /// <returns>
 /// An <see cref="OutgoingMessage"/> instance containing the encrypted and trust verified message.
 /// </returns>
 public OutgoingMessage ProcessOutgoing(string messageText, DirectAddressCollection recipients, DirectAddress sender)
 {
     OutgoingMessage message = new OutgoingMessage(this.WrapMessage(messageText), recipients, sender);            
     return this.ProcessOutgoing(message);            
 }
示例#23
0
 /// <summary>
 /// Encrypts, verifies recipient trust, and signs a MessageEnvelope containing a message to prepare for send.
 /// </summary>
 /// <param name="envelope">
 /// A <see cref="MessageEnvelope"/> instance containing the message to prepare for send.
 /// </param>
 /// <returns>
 /// An <see cref="OutgoingMessage"/> instance containing the encrypted and trust verified message.
 /// </returns>
 public OutgoingMessage ProcessOutgoing(MessageEnvelope envelope)
 {
     if (envelope == null)
     {
         throw new ArgumentNullException("envelope");
     }
     
     OutgoingMessage message = new OutgoingMessage(envelope);
     return this.ProcessOutgoing(message);
 }
示例#24
0
        /// <summary>
        /// Enforces the trust model on an outgoing message by marking
        /// the <c>Status</c> property of <see cref="DirectAddress"/> instances for the receivers
        /// </summary>
        /// <param name="message">The <see cref="OutgoingMessage"/> to validate trust for.</param>
        public void Enforce(OutgoingMessage message)
        {
            if (message == null)
            {
                throw new ArgumentNullException("message");
            }

            DirectAddress sender = message.Sender;

            foreach (DirectAddress recipient in message.Recipients)
            {
                recipient.Status = TrustEnforcementStatus.Failed;

                // The recipient is trusted if we at least one certificate that the sender trusts.
                recipient.Certificates = this.FindTrustedCerts(recipient.Certificates, sender.TrustAnchors);
                if (recipient.HasCertificates)
                {
                    recipient.Status = TrustEnforcementStatus.Success;
                }
            }
        }