Audit mail sent from an address that isn't the sender's own
A group's members can send as the group, and the message says only From: the group, so nothing recorded which person sent it. Every submission whose envelope sender belongs to another account now writes an audit record: the person as actor, an EmailSubmission target named by the address and owned by that account, and "Sent as <address>", with ", from <account>" when it went out through the sender's own account rather than the group's. A delegate's send is left to AL-9's record, and a send from the sender's own address writes nothing. No Sender: header is added: the audit log is where the real sender is named. email_submission_set now takes the access token, from its one caller. The audit suite has a group member send once as the group (one record, with the address, account and details) and once as themselves (none) (specs/multi-account.md, MA-D0a, G2).
This commit is contained in:
1 parent
d7bebd454d
commit
76c170db9d
4 files changed
+165
-1
No files matched your search
@@ -445,6 +445,58 @@ impl Server {
|
||||
}
|
||||
}
|
||||
|
||||
/// MA-D0a: a message sent from an address that isn't the sender's own:
|
||||
/// a group's, today. The message itself only says `From:` the group, so
|
||||
/// the audit log is where the person who sent it is named. A delegate's
|
||||
/// send is AL-9's record, not this one.
|
||||
pub async fn audit_send_as(
|
||||
&self,
|
||||
token: &AccessToken,
|
||||
submission_account_id: u32,
|
||||
submission_id: u32,
|
||||
address: &str,
|
||||
) {
|
||||
let Ok(Some(as_account_id)) = self.account_id_from_email(address, true).await else {
|
||||
return;
|
||||
};
|
||||
if as_account_id == token.account_id() || token.delegation(as_account_id).is_some() {
|
||||
return;
|
||||
}
|
||||
let actor = self.audit_actor(token).await;
|
||||
let tenant_id = self
|
||||
.account(as_account_id)
|
||||
.await
|
||||
.ok()
|
||||
.and_then(|account| account.id_tenant);
|
||||
let details = if submission_account_id == as_account_id {
|
||||
format!("Sent as {address}")
|
||||
} else {
|
||||
format!(
|
||||
"Sent as {address}, from {}",
|
||||
self.audit_account_name(submission_account_id).await
|
||||
)
|
||||
};
|
||||
self.audit_note(Record {
|
||||
at: ms(),
|
||||
actor,
|
||||
via: token.origin().cloned(),
|
||||
remote_ip: None,
|
||||
action: Action::Create,
|
||||
target: Target {
|
||||
kind: "EmailSubmission".into(),
|
||||
id: Some(Id::from(submission_id).to_string()),
|
||||
name: Some(address.to_string()),
|
||||
account_id: Some(as_account_id),
|
||||
tenant_id,
|
||||
},
|
||||
changes: vec![],
|
||||
details: Some(details),
|
||||
reason: None,
|
||||
outcome: Outcome::success(),
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
/// AU-7: removes entries past the retention period.
|
||||
pub async fn audit_purge(&self) -> trc::Result<usize> {
|
||||
let settings = log::settings(self.store()).await?;
|
||||
|
||||
Reference in new issue
Block a user