网站首页 网站源码
website
站点相关全部源代码,隐藏了一些关于服务器的信息
using MailKit;

namespace Dpz.Core.Service;

public sealed class SerilogProtocolLogger(ILogger<SerilogProtocolLogger> logger) : IProtocolLogger
{
    private readonly EventId _eventId = new(10001, "邮件日志");

    private static readonly byte[] Secret = "********"u8.ToArray();

    private static readonly byte[] DefaultClientPrefix = "Client: "u8.ToArray();
    private static readonly byte[] DefaultServerPrefix = "Server: "u8.ToArray();

    private bool _clientMidline;
    private bool _serverMidline;

    private readonly MemoryStream _stream = new();

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    private bool _disposed;

    private void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            if (disposing)
            {
                _stream.Flush();
                _stream.Position = 0;
                using var reader = new StreamReader(_stream);
                var message = reader.ReadToEnd();
                logger.LogInformation(_eventId, message);
                _stream.Dispose();
            }

            _disposed = true;
        }
    }

    ~SerilogProtocolLogger() => Dispose(false);

    public void LogConnect(Uri uri)
    {
        var bytes = Encoding.ASCII.GetBytes($"{DateTime.Now} Connected to {uri}\r\n");
        if (_clientMidline || _serverMidline)
        {
            _clientMidline = false;
            _serverMidline = false;
        }

        _stream.Write(bytes, 0, bytes.Length);
        _stream.Flush();
    }

    public void LogClient(byte[]? buffer, int offset, int count)
    {
        LogBuffer(buffer, offset, count, DefaultClientPrefix, ref _clientMidline, true);
    }

    public void LogServer(byte[]? buffer, int offset, int count)
    {
        LogBuffer(buffer, offset, count, DefaultServerPrefix, ref _serverMidline, false);
    }

    private void LogBuffer(
        byte[]? buffer,
        int offset,
        int count,
        byte[] prefix,
        ref bool midline,
        bool isClient
    )
    {
        if (buffer == null)
        {
            logger.LogError(_eventId, "buffer is null");
            return;
        }

        if (offset < 0 || offset > buffer.Length)
        {
            logger.LogError(
                _eventId,
                "offset less than 0 or offset greater than {Offset}",
                buffer.Length
            );
            return;
        }

        if (count < 0 || count > buffer.Length - offset)
        {
            logger.LogError(
                _eventId,
                "count less than 0 or count greater than {Offset}",
                buffer.Length - offset
            );
            return;
        }

        Log(prefix, ref midline, buffer, offset, count, isClient);
    }

    private void Log(
        byte[] prefix,
        ref bool midline,
        byte[] buffer,
        int offset,
        int count,
        bool isClient
    )
    {
        var number = offset + count;
        var index = offset;
        while (index < number)
        {
            var offset1 = index;
            while (index < number && buffer[index] != 10)
                ++index;
            if (!midline)
            {
                _stream.Write(prefix, 0, prefix.Length);
            }

            if (index < number && buffer[index] == 10)
            {
                midline = false;
                ++index;
            }
            else
                midline = true;

            if (isClient)
            {
                var authenticationSecrets = AuthenticationSecretDetector?.DetectSecrets(
                    buffer,
                    offset1,
                    index - offset1
                );
                if (authenticationSecrets != null)
                {
                    foreach (var detectSecret in authenticationSecrets)
                    {
                        if (detectSecret.StartIndex > offset1)
                            _stream.Write(buffer, offset1, detectSecret.StartIndex - offset1);
                        offset1 = detectSecret.StartIndex + detectSecret.Length;
                        _stream.Write(Secret, 0, Secret.Length);
                    }
                }
            }

            _stream.Write(buffer, offset1, index - offset1);
        }
    }

    public IAuthenticationSecretDetector? AuthenticationSecretDetector { get; set; }
}
⚠⚠    以下内容为AI分析的结果,请根据实际情况进行判断。

这段代码定义了一个名为 SerilogProtocolLogger 的类,它实现了 IProtocolLogger 接口,主要用于记录邮件协议的日志。该类使用了 MailKit 库,并且通过 Serilog 进行日志记录。以下是代码的主要功能和结构的详细解释:

主要功能

  1. 日志记录

    • 该类用于记录与邮件服务器的连接、客户端和服务器之间的通信数据。
    • 它将日志信息写入一个内存流 (MemoryStream),并在适当的时候将其内容记录到日志中。
  2. 连接日志

    • LogConnect(Uri uri) 方法记录与邮件服务器的连接信息,包括连接的时间和 URI。
  3. 客户端和服务器日志

    • LogClient(byte[]? buffer, int offset, int count)LogServer(byte[]? buffer, int offset, int count) 方法分别用于记录客户端和服务器发送的数据。
    • 这些方法会调用 LogBuffer 方法来处理和记录数据。
  4. 数据处理

    • LogBuffer 方法负责检查输入的缓冲区是否有效,并调用 Log 方法来处理实际的日志记录。
    • Log 方法会逐行处理数据,检查是否有换行符,并在每行前添加相应的前缀(客户端或服务器)。
  5. 敏感信息检测

    • 在客户端日志中,Log 方法会使用 AuthenticationSecretDetector 来检测是否有敏感信息(如密码)被发送。如果检测到敏感信息,它会用一个占位符(Secret)替换这些信息,以保护隐私。
  6. 资源管理

    • 类实现了 IDisposable 接口,以确保在不再需要时正确释放资源。Dispose 方法会在对象被销毁时调用,确保内存流被正确处理并记录日志。

代码结构

  • 字段和属性

    • _eventId:用于标识日志事件的 ID。
    • Secret:一个字节数组,用于替换敏感信息。
    • DefaultClientPrefixDefaultServerPrefix:用于标识客户端和服务器日志的前缀。
    • _clientMidline_serverMidline:用于跟踪当前行是否已结束。
    • _stream:用于存储日志信息的内存流。
    • AuthenticationSecretDetector:可选的属性,用于检测敏感信息。
  • 构造函数

    • SerilogProtocolLogger(ILogger<SerilogProtocolLogger> logger):构造函数接受一个 ILogger 实例,用于记录日志。
  • 析构函数

    • ~SerilogProtocolLogger():析构函数,确保在对象被垃圾回收时调用 Dispose 方法。

总结

SerilogProtocolLogger 类是一个用于记录邮件协议交互的日志记录器,能够处理连接信息、客户端和服务器之间的通信,并且能够检测和保护敏感信息。它通过 Serilog 进行日志记录,并实现了资源管理以确保内存的有效使用。

loading