/* * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ use crate::{core::Session, reporting::send::MtaReportSend}; use common::network::SessionStream; use mail_auth::{ AuthenticatedMessage, AuthenticationResults, DkimOutput, common::verify::VerifySignature, }; use registry::schema::structs::Rate; use trc::OutgoingReportEvent; impl Session { pub async fn send_dkim_report( &self, rcpt: &str, message: &AuthenticatedMessage<'_>, rate: &Rate, rejected: bool, output: &DkimOutput<'_>, ) { // Generate report let signature = if let Some(signature) = output.signature() { signature } else { return; }; if self .server .is_local_report_domain(signature.domain(), self.data.session_id) .await { return; } // Throttle recipient if !self.throttle_rcpt(rcpt, rate, "dkim").await { trc::event!( OutgoingReport(OutgoingReportEvent::DkimRateLimited), SpanId = self.data.session_id, To = rcpt.to_string(), Limit = vec![ trc::Value::from(rate.count), trc::Value::from(rate.period.into_inner()) ], ); return; } let config = &self.server.core.smtp.report.dkim; let from_addr = self .server .eval_if(&config.address, self, self.data.session_id) .await .unwrap_or_else(|| "MAILER-DAEMON@localhost".to_string()); let mut report = Vec::with_capacity(128); self.new_auth_failure(output.result().into(), rejected) .with_authentication_results( AuthenticationResults::new(&self.hostname) .with_dkim_result(output, message.from()) .to_string(), ) .with_dkim_domain(signature.domain()) .with_dkim_selector(signature.selector()) .with_dkim_identity(signature.identity()) .with_headers(std::str::from_utf8(message.raw_headers()).unwrap_or_default()) .write_rfc5322( ( self.server .eval_if(&config.name, self, self.data.session_id) .await .unwrap_or_else(|| "Mail Delivery Subsystem".to_string()) .as_str(), from_addr.as_str(), ), rcpt, &self .server .eval_if(&config.subject, self, self.data.session_id) .await .unwrap_or_else(|| "DKIM Report".to_string()), &mut report, ) .ok(); trc::event!( OutgoingReport(OutgoingReportEvent::DkimReport), SpanId = self.data.session_id, From = from_addr.to_string(), To = rcpt.to_string(), ); // Send report self.server .send_report( &from_addr, [rcpt].into_iter(), report, &config.sign, true, self.data.session_id, ) .await; } }