@@ -6,7 +6,7 @@
|
||||
|
||||
use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine};
|
||||
use common::auth::AccessToken;
|
||||
use directory::Permission;
|
||||
use directory::{backend::internal::manage::ManageDirectory, Permission, Type};
|
||||
use hyper::Method;
|
||||
use mail_auth::{
|
||||
dmarc::URI,
|
||||
@@ -21,6 +21,7 @@ use store::{
|
||||
write::{key::DeserializeBigEndian, now, Bincode, QueueClass, ReportEvent, ValueClass},
|
||||
Deserialize, IterateParams, ValueKey,
|
||||
};
|
||||
use trc::AddContext;
|
||||
use utils::url_params::UrlParams;
|
||||
|
||||
use crate::{
|
||||
@@ -111,6 +112,21 @@ impl JMAP {
|
||||
) -> trc::Result<HttpResponse> {
|
||||
let params = UrlParams::new(req.uri().query());
|
||||
|
||||
// Limit to tenant domains
|
||||
let mut tenant_domains = None;
|
||||
if self.core.is_enterprise_edition() {
|
||||
if let Some(tenant) = access_token.tenant {
|
||||
tenant_domains = self
|
||||
.core
|
||||
.storage
|
||||
.data
|
||||
.list_principals(None, Type::Domain.into(), tenant.id.into())
|
||||
.await
|
||||
.caused_by(trc::location!())?
|
||||
.into();
|
||||
}
|
||||
}
|
||||
|
||||
match (
|
||||
path.get(1).copied().unwrap_or_default(),
|
||||
path.get(2).copied().map(decode_path_element),
|
||||
@@ -156,32 +172,35 @@ impl JMAP {
|
||||
IterateParams::new(from_key, to_key).ascending(),
|
||||
|key, value| {
|
||||
let message = Bincode::<queue::Message>::deserialize(value)?.inner;
|
||||
let matches = !has_filters
|
||||
|| (text
|
||||
.as_ref()
|
||||
.map(|text| {
|
||||
message.return_path.contains(text)
|
||||
|| message
|
||||
.recipients
|
||||
.iter()
|
||||
.any(|r| r.address_lcase.contains(text))
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
from.as_ref()
|
||||
.map_or(true, |from| message.return_path.contains(from))
|
||||
&& to.as_ref().map_or(true, |to| {
|
||||
let matches = tenant_domains
|
||||
.as_ref()
|
||||
.map_or(true, |domains| message.has_domain(domains))
|
||||
&& (!has_filters
|
||||
|| (text
|
||||
.as_ref()
|
||||
.map(|text| {
|
||||
message.return_path.contains(text)
|
||||
|| message
|
||||
.recipients
|
||||
.iter()
|
||||
.any(|r| r.address_lcase.contains(text))
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
from.as_ref().map_or(true, |from| {
|
||||
message.return_path.contains(from)
|
||||
}) && to.as_ref().map_or(true, |to| {
|
||||
message
|
||||
.recipients
|
||||
.iter()
|
||||
.any(|r| r.address_lcase.contains(to))
|
||||
})
|
||||
})
|
||||
&& before.as_ref().map_or(true, |before| {
|
||||
message.next_delivery_event() < *before
|
||||
})
|
||||
&& after.as_ref().map_or(true, |after| {
|
||||
message.next_delivery_event() > *after
|
||||
}));
|
||||
})
|
||||
&& before.as_ref().map_or(true, |before| {
|
||||
message.next_delivery_event() < *before
|
||||
})
|
||||
&& after.as_ref().map_or(true, |after| {
|
||||
message.next_delivery_event() > *after
|
||||
})));
|
||||
|
||||
if matches {
|
||||
if offset == 0 {
|
||||
@@ -230,6 +249,11 @@ impl JMAP {
|
||||
.smtp
|
||||
.read_message(queue_id.parse().unwrap_or_default())
|
||||
.await
|
||||
.filter(|message| {
|
||||
tenant_domains
|
||||
.as_ref()
|
||||
.map_or(true, |domains| message.has_domain(domains))
|
||||
})
|
||||
{
|
||||
Ok(JsonResponse::new(json!({
|
||||
"data": Message::from(&message),
|
||||
@@ -253,6 +277,11 @@ impl JMAP {
|
||||
.smtp
|
||||
.read_message(queue_id.parse().unwrap_or_default())
|
||||
.await
|
||||
.filter(|message| {
|
||||
tenant_domains
|
||||
.as_ref()
|
||||
.map_or(true, |domains| message.has_domain(domains))
|
||||
})
|
||||
{
|
||||
let prev_event = message.next_event().unwrap_or_default();
|
||||
let mut found = false;
|
||||
@@ -297,6 +326,11 @@ impl JMAP {
|
||||
.smtp
|
||||
.read_message(queue_id.parse().unwrap_or_default())
|
||||
.await
|
||||
.filter(|message| {
|
||||
tenant_domains
|
||||
.as_ref()
|
||||
.map_or(true, |domains| message.has_domain(domains))
|
||||
})
|
||||
{
|
||||
let mut found = false;
|
||||
let prev_event = message.next_event().unwrap_or_default();
|
||||
@@ -417,7 +451,10 @@ impl JMAP {
|
||||
|key, _| {
|
||||
if type_.map_or(true, |t| t == *key.last().unwrap()) {
|
||||
let event = ReportEvent::deserialize(key)?;
|
||||
if event.seq_id != 0
|
||||
if tenant_domains
|
||||
.as_ref()
|
||||
.map_or(true, |domains| domains.contains(&event.domain))
|
||||
&& event.seq_id != 0
|
||||
&& domain.as_ref().map_or(true, |d| event.domain.contains(d))
|
||||
{
|
||||
if offset == 0 {
|
||||
@@ -460,7 +497,11 @@ impl JMAP {
|
||||
let mut result = None;
|
||||
if let Some(report_id) = parse_queued_report_id(report_id.as_ref()) {
|
||||
match report_id {
|
||||
QueueClass::DmarcReportHeader(event) => {
|
||||
QueueClass::DmarcReportHeader(event)
|
||||
if tenant_domains
|
||||
.as_ref()
|
||||
.map_or(true, |domains| domains.contains(&event.domain)) =>
|
||||
{
|
||||
let mut rua = Vec::new();
|
||||
if let Some(report) = self
|
||||
.smtp
|
||||
@@ -470,7 +511,11 @@ impl JMAP {
|
||||
result = Report::dmarc(event, report, rua).into();
|
||||
}
|
||||
}
|
||||
QueueClass::TlsReportHeader(event) => {
|
||||
QueueClass::TlsReportHeader(event)
|
||||
if tenant_domains
|
||||
.as_ref()
|
||||
.map_or(true, |domains| domains.contains(&event.domain)) =>
|
||||
{
|
||||
let mut rua = Vec::new();
|
||||
if let Some(report) = self
|
||||
.smtp
|
||||
@@ -498,18 +543,28 @@ impl JMAP {
|
||||
access_token.assert_has_permission(Permission::OutgoingReportDelete)?;
|
||||
|
||||
if let Some(report_id) = parse_queued_report_id(report_id.as_ref()) {
|
||||
match report_id {
|
||||
QueueClass::DmarcReportHeader(event) => {
|
||||
let result = match report_id {
|
||||
QueueClass::DmarcReportHeader(event)
|
||||
if tenant_domains
|
||||
.as_ref()
|
||||
.map_or(true, |domains| domains.contains(&event.domain)) =>
|
||||
{
|
||||
self.smtp.delete_dmarc_report(event).await;
|
||||
true
|
||||
}
|
||||
QueueClass::TlsReportHeader(event) => {
|
||||
QueueClass::TlsReportHeader(event)
|
||||
if tenant_domains
|
||||
.as_ref()
|
||||
.map_or(true, |domains| domains.contains(&event.domain)) =>
|
||||
{
|
||||
self.smtp.delete_tls_report(vec![event]).await;
|
||||
true
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
_ => false,
|
||||
};
|
||||
|
||||
Ok(JsonResponse::new(json!({
|
||||
"data": true,
|
||||
"data": result,
|
||||
}))
|
||||
.into_http_response())
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user