/// <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()); } }
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); } }
/// <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); } }
//------------------------------------------------------------------- // // 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); }
void Notify(OutgoingMessage message, Action<OutgoingMessage> eventHandler) { // // exceptions are interpreted as: abort message // if (eventHandler != null) { eventHandler(message); } }
// // 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); } }
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; } } }
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); }
/// <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; }
//--------------------------------------------------- // // Outgoing // //--------------------------------------------------- void OnPreProcessOutgoing(OutgoingMessage message) { if (m_settings.HasAddressManager) { VerifySenderAddress(message); } }
void Notify(OutgoingMessage message, Exception ex) { try { Action<OutgoingMessage, Exception> errorOutgoing = ErrorOutgoing; if (errorOutgoing != null) { errorOutgoing(message, ex); } } catch { } }
/// <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)); }
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()); } }
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(); } }
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; }
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); } }
// // 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; }
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())); }
/// <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); }
/// <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); }
/// <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; } } }