mail-server/crates/trc/src/lib.rs

977 lines
16 KiB
Rust

/*
* SPDX-FileCopyrightText: 2020 Stalwart Labs Ltd <hello@stalw.art>
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
*/
pub mod atomics;
pub mod event;
pub mod ipc;
pub mod macros;
pub mod serializers;
use std::{
net::{IpAddr, Ipv4Addr, Ipv6Addr},
sync::Arc,
};
pub use crate::ipc::collector::Collector;
pub use event_macro::event;
use event_macro::{event_family, event_type, key_names, total_event_count};
pub type Result<T> = std::result::Result<T, Error>;
pub type Error = Event<EventType>;
#[derive(Debug, Clone)]
pub struct Event<T> {
pub inner: T,
pub keys: Vec<(Key, Value)>,
}
#[derive(Debug, Clone)]
pub struct EventDetails {
pub typ: EventType,
pub timestamp: u64,
pub level: Level,
pub span: Option<Arc<Event<EventDetails>>>,
}
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
#[repr(usize)]
pub enum Level {
Trace = 0,
Debug = 1,
Info = 2,
Warn = 3,
Error = 4,
Disable = 5,
}
#[derive(Debug, Default, Clone)]
pub enum Value {
Static(&'static str),
String(String),
UInt(u64),
Int(i64),
Float(f64),
Timestamp(u64),
Duration(u64),
Bytes(Vec<u8>),
Bool(bool),
Ipv4(Ipv4Addr),
Ipv6(Ipv6Addr),
Event(Event<EventType>),
Array(Vec<Value>),
#[default]
None,
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
#[key_names]
pub enum Key {
AccountName,
AccountId,
BlobId,
#[default]
CausedBy,
ChangeId,
Code,
Collection,
Contents,
Details,
DkimFail,
DkimNone,
DkimPass,
DmarcNone,
DmarcPass,
DmarcQuarantine,
DmarcReject,
DocumentId,
Domain,
Due,
Elapsed,
Expires,
From,
Hostname,
Id,
Key,
Limit,
ListenerId,
LocalIp,
LocalPort,
MailboxName,
MailboxId,
MessageId,
NextDsn,
NextRetry,
Path,
Policy,
QueueId,
RangeFrom,
RangeTo,
Reason,
RemoteIp,
RemotePort,
ReportId,
Result,
Size,
Source,
SpanId,
SpfFail,
SpfNone,
SpfPass,
Strict,
Tls,
To,
Total,
TotalFailures,
TotalSuccesses,
Type,
Uid,
UidNext,
UidValidity,
Url,
ValidFrom,
ValidTo,
Value,
Version,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[event_family]
pub enum EventType {
Server(ServerEvent),
Purge(PurgeEvent),
Eval(EvalEvent),
Acme(AcmeEvent),
Store(StoreEvent),
MessageIngest(MessageIngestEvent),
Jmap(JmapEvent),
Imap(ImapEvent),
ManageSieve(ManageSieveEvent),
Pop3(Pop3Event),
Smtp(SmtpEvent),
Http(HttpEvent),
Network(NetworkEvent),
Limit(LimitEvent),
Manage(ManageEvent),
Auth(AuthEvent),
Config(ConfigEvent),
Resource(ResourceEvent),
Arc(ArcEvent),
Dkim(DkimEvent),
Dmarc(DmarcEvent),
Iprev(IprevEvent),
Dane(DaneEvent),
Spf(SpfEvent),
MailAuth(MailAuthEvent),
Tls(TlsEvent),
Sieve(SieveEvent),
Spam(SpamEvent),
PushSubscription(PushSubscriptionEvent),
Cluster(ClusterEvent),
Housekeeper(HousekeeperEvent),
FtsIndex(FtsIndexEvent),
Milter(MilterEvent),
MtaHook(MtaHookEvent),
Delivery(DeliveryEvent),
Queue(QueueEvent),
TlsRpt(TlsRptEvent),
MtaSts(MtaStsEvent),
IncomingReport(IncomingReportEvent),
OutgoingReport(OutgoingReportEvent),
Telemetry(TelemetryEvent),
Security(SecurityEvent),
}
#[event_type]
pub enum HttpEvent {
ConnectionStart,
ConnectionEnd,
Error,
RequestUrl,
RequestBody,
ResponseBody,
XForwardedMissing,
}
#[event_type]
pub enum SecurityEvent {
AuthenticationBan,
BruteForceBan,
LoiterBan,
IpBlocked,
}
#[event_type]
pub enum ClusterEvent {
PeerAlive,
PeerDiscovered,
PeerOffline,
PeerSuspected,
PeerSuspectedIsAlive,
PeerBackOnline,
PeerLeaving,
PeerHasConfigChanges,
PeerHasListChanges,
OneOrMorePeersOffline,
EmptyPacket,
InvalidPacket,
DecryptionError,
Error,
}
#[event_type]
pub enum HousekeeperEvent {
Start,
Stop,
Schedule,
PurgeAccounts,
PurgeSessions,
PurgeStore,
}
#[event_type]
pub enum FtsIndexEvent {
Index,
Locked,
LockBusy,
BlobNotFound,
MetadataNotFound,
}
#[event_type]
pub enum ImapEvent {
ConnectionStart,
ConnectionEnd,
// Commands
GetAcl,
SetAcl,
MyRights,
ListRights,
Append,
Capabilities,
Id,
Close,
Copy,
Move,
CreateMailbox,
DeleteMailbox,
RenameMailbox,
Enable,
Expunge,
Fetch,
IdleStart,
IdleStop,
List,
Lsub,
Logout,
Namespace,
Noop,
Search,
Sort,
Select,
Status,
Store,
Subscribe,
Unsubscribe,
Thread,
// Errors
Error,
// Debugging
RawInput,
RawOutput,
}
#[event_type]
pub enum Pop3Event {
ConnectionStart,
ConnectionEnd,
// Commands
Delete,
Reset,
Quit,
Fetch,
List,
ListMessage,
Uidl,
UidlMessage,
Stat,
Noop,
Capabilities,
StartTls,
Utf8,
// Errors
Error,
// Debugging
RawInput,
RawOutput,
}
#[event_type]
pub enum ManageSieveEvent {
ConnectionStart,
ConnectionEnd,
// Commands
CreateScript,
UpdateScript,
GetScript,
DeleteScript,
RenameScript,
CheckScript,
HaveSpace,
ListScripts,
SetActive,
Capabilities,
StartTls,
Unauthenticate,
Logout,
Noop,
// Errors
Error,
// Debugging
RawInput,
RawOutput,
}
#[event_type]
pub enum SmtpEvent {
ConnectionStart,
ConnectionEnd,
Error,
RemoteIdNotFound,
ConcurrencyLimitExceeded,
TransferLimitExceeded,
RateLimitExceeded,
TimeLimitExceeded,
MissingAuthDirectory,
MessageParseFailed,
MessageTooLarge,
LoopDetected,
PipeSuccess,
PipeError,
DkimPass,
DkimFail,
ArcPass,
ArcFail,
SpfEhloPass,
SpfEhloFail,
SpfFromPass,
SpfFromFail,
DmarcPass,
DmarcFail,
IprevPass,
IprevFail,
TooManyMessages,
Ehlo,
InvalidEhlo,
DidNotSayEhlo,
EhloExpected,
LhloExpected,
MailFromUnauthenticated,
MailFromUnauthorized,
MailFromNotAllowed,
MailFromRewritten,
MailFromMissing,
MailFrom,
MultipleMailFrom,
MailboxDoesNotExist,
RelayNotAllowed,
RcptTo,
RcptToDuplicate,
RcptToRewritten,
RcptToMissing,
TooManyRecipients,
TooManyInvalidRcpt,
RawInput,
RawOutput,
MissingLocalHostname,
Vrfy,
VrfyNotFound,
VrfyDisabled,
Expn,
ExpnNotFound,
ExpnDisabled,
RequireTlsDisabled,
DeliverByDisabled,
DeliverByInvalid,
FutureReleaseDisabled,
FutureReleaseInvalid,
MtPriorityDisabled,
MtPriorityInvalid,
DsnDisabled,
AuthNotAllowed,
AuthMechanismNotSupported,
AuthExchangeTooLong,
AlreadyAuthenticated,
Noop,
StartTls,
StartTlsUnavailable,
StartTlsAlready,
Rset,
Quit,
Help,
CommandNotImplemented,
InvalidCommand,
InvalidSenderAddress,
InvalidRecipientAddress,
InvalidParameter,
UnsupportedParameter,
SyntaxError,
RequestTooLarge,
}
#[event_type]
pub enum DeliveryEvent {
AttemptStart,
AttemptEnd,
Completed,
Failed,
DomainDeliveryStart,
MxLookup,
MxLookupFailed,
IpLookup,
IpLookupFailed,
NullMx,
Connect,
ConnectError,
MissingOutboundHostname,
GreetingFailed,
Ehlo,
EhloRejected,
Auth,
AuthFailed,
MailFrom,
MailFromRejected,
Delivered,
RcptTo,
RcptToRejected,
RcptToFailed,
MessageRejected,
StartTls,
StartTlsUnavailable,
StartTlsError,
StartTlsDisabled,
ImplicitTlsError,
ConcurrencyLimitExceeded,
RateLimitExceeded,
DoubleBounce,
DsnSuccess,
DsnTempFail,
DsnPermFail,
RawInput,
RawOutput,
}
#[event_type]
pub enum QueueEvent {
QueueMessage,
QueueMessageAuthenticated,
QueueReport,
QueueDsn,
QueueAutogenerated,
Rescheduled,
LockBusy,
Locked,
BlobNotFound,
RateLimitExceeded,
ConcurrencyLimitExceeded,
QuotaExceeded,
}
#[event_type]
pub enum IncomingReportEvent {
DmarcReport,
DmarcReportWithWarnings,
TlsReport,
TlsReportWithWarnings,
AbuseReport,
AuthFailureReport,
FraudReport,
NotSpamReport,
VirusReport,
OtherReport,
MessageParseFailed,
DmarcParseFailed,
TlsRpcParseFailed,
ArfParseFailed,
DecompressError,
}
#[event_type]
pub enum OutgoingReportEvent {
SpfReport,
SpfRateLimited,
DkimReport,
DkimRateLimited,
DmarcReport,
DmarcRateLimited,
DmarcAggregateReport,
TlsAggregate,
HttpSubmission,
UnauthorizedReportingAddress,
ReportingAddressValidationError,
NotFound,
SubmissionError,
NoRecipientsFound,
LockBusy,
LockDeleted,
Locked,
}
#[event_type]
pub enum MtaStsEvent {
Authorized,
NotAuthorized,
PolicyFetch,
PolicyNotFound,
PolicyFetchError,
InvalidPolicy,
}
#[event_type]
pub enum TlsRptEvent {
RecordFetch,
RecordFetchError,
}
#[event_type]
pub enum DaneEvent {
AuthenticationSuccess,
AuthenticationFailure,
NoCertificatesFound,
CertificateParseError,
TlsaRecordMatch,
TlsaRecordFetch,
TlsaRecordFetchError,
TlsaRecordNotFound,
TlsaRecordNotDnssecSigned,
TlsaRecordInvalid,
}
#[event_type]
pub enum MilterEvent {
Read,
Write,
ActionAccept,
ActionDiscard,
ActionReject,
ActionTempFail,
ActionReplyCode,
ActionConnectionFailure,
ActionShutdown,
IoError,
FrameTooLarge,
FrameInvalid,
UnexpectedResponse,
Timeout,
TlsInvalidName,
Disconnected,
ParseError,
}
#[event_type]
pub enum MtaHookEvent {
ActionAccept,
ActionDiscard,
ActionReject,
ActionQuarantine,
Error,
}
#[event_type]
pub enum PushSubscriptionEvent {
Success,
Error,
NotFound,
}
#[event_type]
pub enum SpamEvent {
PyzorError,
ListUpdated,
Train,
TrainBalance,
TrainError,
Classify,
ClassifyError,
NotEnoughTrainingData,
}
#[event_type]
pub enum SieveEvent {
ActionAccept,
ActionAcceptReplace,
ActionDiscard,
ActionReject,
SendMessage,
MessageTooLarge,
ScriptNotFound,
ListNotFound,
RuntimeError,
UnexpectedError,
NotSupported,
QuotaExceeded,
}
#[event_type]
pub enum TlsEvent {
Handshake,
HandshakeError,
NotConfigured,
CertificateNotFound,
NoCertificatesAvailable,
MultipleCertificatesAvailable,
}
#[event_type]
pub enum NetworkEvent {
ListenStart,
ListenStop,
ListenError,
BindError,
ReadError,
WriteError,
FlushError,
AcceptError,
SplitError,
Timeout,
Closed,
ProxyError,
SetOptError,
}
#[event_type]
pub enum ServerEvent {
Startup,
Shutdown,
StartupError,
ThreadError,
Licensing,
}
#[event_type]
pub enum TelemetryEvent {
Alert,
LogError,
WebhookError,
OtelExporterError,
OtelMetricsExporterError,
PrometheusExporterError,
JournalError,
}
#[event_type]
pub enum AcmeEvent {
AuthStart,
AuthPending,
AuthValid,
AuthCompleted,
AuthError,
AuthTooManyAttempts,
ProcessCert,
OrderStart,
OrderProcessing,
OrderCompleted,
OrderReady,
OrderValid,
OrderInvalid,
RenewBackoff,
DnsRecordCreated,
DnsRecordCreationFailed,
DnsRecordDeletionFailed,
DnsRecordNotPropagated,
DnsRecordLookupFailed,
DnsRecordPropagated,
DnsRecordPropagationTimeout,
ClientSuppliedSni,
ClientMissingSni,
TlsAlpnReceived,
TlsAlpnError,
TokenNotFound,
Error,
}
#[event_type]
pub enum PurgeEvent {
Started,
Finished,
Running,
Error,
PurgeActive,
AutoExpunge,
TombstoneCleanup,
}
#[event_type]
pub enum EvalEvent {
Result,
Error,
DirectoryNotFound,
StoreNotFound,
}
#[event_type]
pub enum ConfigEvent {
ParseError,
BuildError,
MacroError,
WriteError,
FetchError,
DefaultApplied,
MissingSetting,
UnusedSetting,
ParseWarning,
BuildWarning,
ImportExternal,
ExternalKeyIgnored,
AlreadyUpToDate,
}
#[event_type]
pub enum ArcEvent {
ChainTooLong,
InvalidInstance,
InvalidCv,
HasHeaderTag,
BrokenChain,
SealerNotFound,
}
#[event_type]
pub enum DkimEvent {
Pass,
Neutral,
Fail,
PermError,
TempError,
None,
UnsupportedVersion,
UnsupportedAlgorithm,
UnsupportedCanonicalization,
UnsupportedKeyType,
FailedBodyHashMatch,
FailedVerification,
FailedAuidMatch,
RevokedPublicKey,
IncompatibleAlgorithms,
SignatureExpired,
SignatureLength,
SignerNotFound,
}
#[event_type]
pub enum SpfEvent {
Pass,
Fail,
SoftFail,
Neutral,
TempError,
PermError,
None,
}
#[event_type]
pub enum DmarcEvent {
Pass,
Fail,
PermError,
TempError,
None,
}
#[event_type]
pub enum IprevEvent {
Pass,
Fail,
PermError,
TempError,
None,
}
#[event_type]
pub enum MailAuthEvent {
ParseError,
MissingParameters,
NoHeadersFound,
Crypto,
Io,
Base64,
DnsError,
DnsRecordNotFound,
DnsInvalidRecordType,
PolicyNotAligned,
}
#[event_type]
pub enum StoreEvent {
// Errors
AssertValueFailed,
FoundationdbError,
MysqlError,
PostgresqlError,
RocksdbError,
SqliteError,
LdapError,
ElasticsearchError,
RedisError,
S3Error,
FilesystemError,
PoolError,
DataCorruption,
DecompressError,
DeserializeError,
NotFound,
NotConfigured,
NotSupported,
UnexpectedError,
CryptoError,
// Warnings
BlobMissingMarker,
// Traces
DataWrite,
DataIterate,
BlobRead,
BlobWrite,
BlobDelete,
SqlQuery,
LdapQuery,
LdapBind,
}
#[event_type]
pub enum MessageIngestEvent {
// Events
Ham,
Spam,
ImapAppend,
JmapAppend,
Duplicate,
Error,
}
#[event_type]
pub enum JmapEvent {
// Calls
MethodCall,
// Method errors
InvalidArguments,
RequestTooLarge,
StateMismatch,
AnchorNotFound,
UnsupportedFilter,
UnsupportedSort,
UnknownMethod,
InvalidResultReference,
Forbidden,
AccountNotFound,
AccountNotSupportedByMethod,
AccountReadOnly,
NotFound,
CannotCalculateChanges,
UnknownDataType,
// Request errors
UnknownCapability,
NotJson,
NotRequest,
// Not JMAP standard
WebsocketStart,
WebsocketStop,
WebsocketError,
}
#[event_type]
pub enum LimitEvent {
SizeRequest,
SizeUpload,
CallsIn,
ConcurrentRequest,
ConcurrentUpload,
ConcurrentConnection, // Used by listener
Quota,
BlobQuota,
TooManyRequests,
}
#[event_type]
pub enum ManageEvent {
MissingParameter,
AlreadyExists,
AssertFailed,
NotFound,
NotSupported,
Error,
}
#[event_type]
pub enum AuthEvent {
Success,
Failed,
MissingTotp,
TooManyAttempts,
Error,
}
#[event_type]
pub enum ResourceEvent {
NotFound,
BadParameters,
Error,
DownloadExternal,
WebadminUnpacked,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum MetricType {
ServerMemory,
MessageIngestionTime,
MessageFtsIndexTime,
MessageSize,
MessageAuthSize,
DeliveryTotalTime,
DeliveryTime,
DeliveryActiveConnections,
QueueCount,
ReportOutgoingSize,
StoreReadTime,
StoreWriteTime,
BlobReadTime,
BlobWriteTime,
DnsLookupTime,
HttpActiveConnections,
HttpRequestTime,
ImapActiveConnections,
ImapRequestTime,
Pop3ActiveConnections,
Pop3RequestTime,
SmtpActiveConnections,
SmtpRequestTime,
SieveActiveConnections,
SieveRequestTime,
UserCount,
DomainCount,
}
pub const TOTAL_EVENT_COUNT: usize = total_event_count!();
pub trait AddContext<T> {
fn caused_by(self, location: &'static str) -> Result<T>;
fn add_context<F>(self, f: F) -> Result<T>
where
F: FnOnce(Error) -> Error;
}