diff --git a/DMS.Application/DTOs/CreateEmailAccountRequest.cs b/DMS.Application/DTOs/CreateEmailAccountRequest.cs
new file mode 100644
index 0000000..b45a6d3
--- /dev/null
+++ b/DMS.Application/DTOs/CreateEmailAccountRequest.cs
@@ -0,0 +1,63 @@
+namespace DMS.Application.DTOs
+{
+ ///
+ /// 创建邮件账户请求DTO
+ ///
+ public class CreateEmailAccountRequest
+ {
+ ///
+ /// 账户名称
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// 邮箱地址
+ ///
+ public string EmailAddress { get; set; }
+
+ ///
+ /// SMTP服务器地址
+ ///
+ public string SmtpServer { get; set; }
+
+ ///
+ /// SMTP端口号
+ ///
+ public int SmtpPort { get; set; } = 587;
+
+ ///
+ /// 是否启用SSL
+ ///
+ public bool EnableSsl { get; set; } = true;
+
+ ///
+ /// 用户名
+ ///
+ public string Username { get; set; }
+
+ ///
+ /// 密码
+ ///
+ public string Password { get; set; }
+
+ ///
+ /// IMAP服务器地址
+ ///
+ public string? ImapServer { get; set; }
+
+ ///
+ /// IMAP端口号
+ ///
+ public int ImapPort { get; set; } = 993;
+
+ ///
+ /// 是否为默认账户
+ ///
+ public bool IsDefault { get; set; }
+
+ ///
+ /// 是否启用
+ ///
+ public bool IsActive { get; set; } = true;
+ }
+}
\ No newline at end of file
diff --git a/DMS.Application/DTOs/EmailAccountDto.cs b/DMS.Application/DTOs/EmailAccountDto.cs
new file mode 100644
index 0000000..80a722c
--- /dev/null
+++ b/DMS.Application/DTOs/EmailAccountDto.cs
@@ -0,0 +1,73 @@
+namespace DMS.Application.DTOs
+{
+ ///
+ /// 邮件账户DTO
+ ///
+ public class EmailAccountDto
+ {
+ ///
+ /// 账户ID
+ ///
+ public int Id { get; set; }
+
+ ///
+ /// 账户名称
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// 邮箱地址
+ ///
+ public string EmailAddress { get; set; }
+
+ ///
+ /// SMTP服务器地址
+ ///
+ public string SmtpServer { get; set; }
+
+ ///
+ /// SMTP端口号
+ ///
+ public int SmtpPort { get; set; }
+
+ ///
+ /// 是否启用SSL
+ ///
+ public bool EnableSsl { get; set; }
+
+ ///
+ /// 用户名
+ ///
+ public string Username { get; set; }
+
+ ///
+ /// IMAP服务器地址
+ ///
+ public string? ImapServer { get; set; }
+
+ ///
+ /// IMAP端口号
+ ///
+ public int ImapPort { get; set; }
+
+ ///
+ /// 是否为默认账户
+ ///
+ public bool IsDefault { get; set; }
+
+ ///
+ /// 是否启用
+ ///
+ public bool IsActive { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ public DateTime CreatedAt { get; set; }
+
+ ///
+ /// 更新时间
+ ///
+ public DateTime UpdatedAt { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/DMS.Application/DTOs/EmailLogDto.cs b/DMS.Application/DTOs/EmailLogDto.cs
new file mode 100644
index 0000000..d0e322f
--- /dev/null
+++ b/DMS.Application/DTOs/EmailLogDto.cs
@@ -0,0 +1,38 @@
+namespace DMS.Application.DTOs
+{
+ ///
+ /// 邮件日志DTO
+ ///
+ public class EmailLogDto
+ {
+ ///
+ /// 日志ID
+ ///
+ public int Id { get; set; }
+
+ ///
+ /// 关联的邮件ID
+ ///
+ public int EmailMessageId { get; set; }
+
+ ///
+ /// 日志级别
+ ///
+ public string Level { get; set; }
+
+ ///
+ /// 日志消息
+ ///
+ public string Message { get; set; }
+
+ ///
+ /// 异常详情
+ ///
+ public string? Exception { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ public DateTime CreatedAt { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/DMS.Application/DTOs/EmailMessageDto.cs b/DMS.Application/DTOs/EmailMessageDto.cs
new file mode 100644
index 0000000..459cc3e
--- /dev/null
+++ b/DMS.Application/DTOs/EmailMessageDto.cs
@@ -0,0 +1,73 @@
+namespace DMS.Application.DTOs
+{
+ ///
+ /// 邮件消息DTO
+ ///
+ public class EmailMessageDto
+ {
+ ///
+ /// 邮件ID
+ ///
+ public int Id { get; set; }
+
+ ///
+ /// 关联的邮件账户ID
+ ///
+ public int EmailAccountId { get; set; }
+
+ ///
+ /// 发件人邮箱地址
+ ///
+ public string From { get; set; }
+
+ ///
+ /// 收件人邮箱地址(多个用分号分隔)
+ ///
+ public string To { get; set; }
+
+ ///
+ /// 抄送邮箱地址(多个用分号分隔)
+ ///
+ public string? Cc { get; set; }
+
+ ///
+ /// 密送邮箱地址(多个用分号分隔)
+ ///
+ public string? Bcc { get; set; }
+
+ ///
+ /// 邮件主题
+ ///
+ public string Subject { get; set; }
+
+ ///
+ /// 邮件正文
+ ///
+ public string Body { get; set; }
+
+ ///
+ /// 是否为HTML格式
+ ///
+ public bool IsHtml { get; set; }
+
+ ///
+ /// 邮件发送状态
+ ///
+ public string Status { get; set; }
+
+ ///
+ /// 发送时间
+ ///
+ public DateTime? SentAt { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ public DateTime CreatedAt { get; set; }
+
+ ///
+ /// 更新时间
+ ///
+ public DateTime UpdatedAt { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/DMS.Application/DTOs/EmailTemplateDto.cs b/DMS.Application/DTOs/EmailTemplateDto.cs
new file mode 100644
index 0000000..bf1ec9c
--- /dev/null
+++ b/DMS.Application/DTOs/EmailTemplateDto.cs
@@ -0,0 +1,53 @@
+namespace DMS.Application.DTOs
+{
+ ///
+ /// 邮件模板DTO
+ ///
+ public class EmailTemplateDto
+ {
+ ///
+ /// 模板ID
+ ///
+ public int Id { get; set; }
+
+ ///
+ /// 模板名称
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// 模板代码(唯一标识)
+ ///
+ public string Code { get; set; }
+
+ ///
+ /// 模板主题
+ ///
+ public string Subject { get; set; }
+
+ ///
+ /// 模板内容
+ ///
+ public string Body { get; set; }
+
+ ///
+ /// 是否为HTML格式
+ ///
+ public bool IsHtml { get; set; }
+
+ ///
+ /// 是否启用
+ ///
+ public bool IsActive { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ public DateTime CreatedAt { get; set; }
+
+ ///
+ /// 更新时间
+ ///
+ public DateTime UpdatedAt { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/DMS.Application/DTOs/SendEmailRequest.cs b/DMS.Application/DTOs/SendEmailRequest.cs
new file mode 100644
index 0000000..18f4ebc
--- /dev/null
+++ b/DMS.Application/DTOs/SendEmailRequest.cs
@@ -0,0 +1,43 @@
+namespace DMS.Application.DTOs
+{
+ ///
+ /// 发送邮件请求DTO
+ ///
+ public class SendEmailRequest
+ {
+ ///
+ /// 关联的邮件账户ID
+ ///
+ public int EmailAccountId { get; set; }
+
+ ///
+ /// 收件人邮箱地址(多个用分号分隔)
+ ///
+ public string To { get; set; }
+
+ ///
+ /// 抄送邮箱地址(多个用分号分隔)
+ ///
+ public string? Cc { get; set; }
+
+ ///
+ /// 密送邮箱地址(多个用分号分隔)
+ ///
+ public string? Bcc { get; set; }
+
+ ///
+ /// 邮件主题
+ ///
+ public string Subject { get; set; }
+
+ ///
+ /// 邮件正文
+ ///
+ public string Body { get; set; }
+
+ ///
+ /// 是否为HTML格式
+ ///
+ public bool IsHtml { get; set; } = true;
+ }
+}
\ No newline at end of file
diff --git a/DMS.Application/Interfaces/IEmailAppService.cs b/DMS.Application/Interfaces/IEmailAppService.cs
new file mode 100644
index 0000000..d8144d2
--- /dev/null
+++ b/DMS.Application/Interfaces/IEmailAppService.cs
@@ -0,0 +1,75 @@
+using DMS.Application.DTOs;
+
+namespace DMS.Application.Interfaces
+{
+ ///
+ /// 邮件应用服务接口
+ ///
+ public interface IEmailAppService
+ {
+ ///
+ /// 获取所有邮件账户
+ ///
+ Task> GetAllEmailAccountsAsync();
+
+ ///
+ /// 根据ID获取邮件账户
+ ///
+ Task GetEmailAccountByIdAsync(int id);
+
+ ///
+ /// 创建邮件账户
+ ///
+ Task CreateEmailAccountAsync(CreateEmailAccountRequest request);
+
+ ///
+ /// 更新邮件账户
+ ///
+ Task UpdateEmailAccountAsync(int id, CreateEmailAccountRequest request);
+
+ ///
+ /// 删除邮件账户
+ ///
+ Task DeleteEmailAccountAsync(int id);
+
+ ///
+ /// 测试邮件账户连接
+ ///
+ Task TestEmailAccountAsync(int id);
+
+ ///
+ /// 发送邮件
+ ///
+ Task SendEmailAsync(SendEmailRequest request);
+
+ ///
+ /// 获取所有邮件模板
+ ///
+ Task> GetAllEmailTemplatesAsync();
+
+ ///
+ /// 根据ID获取邮件模板
+ ///
+ Task GetEmailTemplateByIdAsync(int id);
+
+ ///
+ /// 根据代码获取邮件模板
+ ///
+ Task GetEmailTemplateByCodeAsync(string code);
+
+ ///
+ /// 创建邮件模板
+ ///
+ Task CreateEmailTemplateAsync(EmailTemplateDto template);
+
+ ///
+ /// 更新邮件模板
+ ///
+ Task UpdateEmailTemplateAsync(int id, EmailTemplateDto template);
+
+ ///
+ /// 删除邮件模板
+ ///
+ Task DeleteEmailTemplateAsync(int id);
+ }
+}
\ No newline at end of file
diff --git a/DMS.Application/Profiles/MappingProfile.cs b/DMS.Application/Profiles/MappingProfile.cs
index d42d71d..5501201 100644
--- a/DMS.Application/Profiles/MappingProfile.cs
+++ b/DMS.Application/Profiles/MappingProfile.cs
@@ -11,14 +11,9 @@ public class MappingProfile : Profile
{
public MappingProfile()
{
-
-
-
CreateMap()
.ReverseMap();
-
-
// VariableTable 映射
CreateMap().ReverseMap();
@@ -26,11 +21,9 @@ public class MappingProfile : Profile
CreateMap()
.ReverseMap();
-
CreateMap()
.ReverseMap();
-
// MqttServer 映射
CreateMap().ReverseMap();
@@ -50,5 +43,18 @@ public class MappingProfile : Profile
// User 映射
CreateMap().ReverseMap();
CreateMap().ReverseMap();
+
+ // 邮件相关映射
+ CreateMap().ReverseMap();
+ CreateMap().ReverseMap();
+
+ CreateMap().ReverseMap();
+ CreateMap()
+ .ForMember(dest => dest.EmailAccountId, opt => opt.MapFrom(src => src.EmailAccountId))
+ .ReverseMap();
+
+ CreateMap().ReverseMap();
+
+ CreateMap().ReverseMap();
}
}
diff --git a/DMS.Application/Services/EmailAppService.cs b/DMS.Application/Services/EmailAppService.cs
new file mode 100644
index 0000000..2d7d34d
--- /dev/null
+++ b/DMS.Application/Services/EmailAppService.cs
@@ -0,0 +1,185 @@
+using AutoMapper;
+using DMS.Application.DTOs;
+using DMS.Application.Interfaces;
+using DMS.Core.Interfaces.Repositories;
+using DMS.Core.Interfaces.Services;
+using DMS.Core.Models;
+
+namespace DMS.Application.Services
+{
+ ///
+ /// 邮件应用服务实现
+ ///
+ public class EmailAppService : IEmailAppService
+ {
+ private readonly IEmailAccountRepository _emailAccountRepository;
+ private readonly IEmailTemplateRepository _emailTemplateRepository;
+ private readonly IEmailMessageRepository _emailMessageRepository;
+ private readonly IEmailService _emailService;
+ private readonly IMapper _mapper;
+
+ public EmailAppService(
+ IEmailAccountRepository emailAccountRepository,
+ IEmailTemplateRepository emailTemplateRepository,
+ IEmailMessageRepository emailMessageRepository,
+ IEmailService emailService,
+ IMapper mapper)
+ {
+ _emailAccountRepository = emailAccountRepository;
+ _emailTemplateRepository = emailTemplateRepository;
+ _emailMessageRepository = emailMessageRepository;
+ _emailService = emailService;
+ _mapper = mapper;
+ }
+
+ ///
+ /// 获取所有邮件账户
+ ///
+ public async Task> GetAllEmailAccountsAsync()
+ {
+ var accounts = await _emailAccountRepository.GetAllAsync();
+ return _mapper.Map>(accounts);
+ }
+
+ ///
+ /// 根据ID获取邮件账户
+ ///
+ public async Task GetEmailAccountByIdAsync(int id)
+ {
+ var account = await _emailAccountRepository.GetByIdAsync(id);
+ return _mapper.Map(account);
+ }
+
+ ///
+ /// 创建邮件账户
+ ///
+ public async Task CreateEmailAccountAsync(CreateEmailAccountRequest request)
+ {
+ var account = _mapper.Map(request);
+ var createdAccount = await _emailAccountRepository.AddAsync(account);
+ return _mapper.Map(createdAccount);
+ }
+
+ ///
+ /// 更新邮件账户
+ ///
+ public async Task UpdateEmailAccountAsync(int id, CreateEmailAccountRequest request)
+ {
+ var existingAccount = await _emailAccountRepository.GetByIdAsync(id);
+ if (existingAccount == null)
+ throw new ArgumentException($"未找到ID为 {id} 的邮件账户");
+
+ _mapper.Map(request, existingAccount);
+ existingAccount.UpdatedAt = DateTime.Now;
+
+ var updatedAccount = await _emailAccountRepository.UpdateAsync(existingAccount);
+ return _mapper.Map(existingAccount);
+ }
+
+ ///
+ /// 删除邮件账户
+ ///
+ public async Task DeleteEmailAccountAsync(int id)
+ {
+ var account = await _emailAccountRepository.GetByIdAsync(id);
+ if (account == null)
+ return false;
+
+ await _emailAccountRepository.DeleteAsync(account);
+ return true;
+ }
+
+ ///
+ /// 测试邮件账户连接
+ ///
+ public async Task TestEmailAccountAsync(int id)
+ {
+ var account = await _emailAccountRepository.GetByIdAsync(id);
+ if (account == null)
+ return false;
+
+ return await _emailService.TestConnectionAsync(account);
+ }
+
+ ///
+ /// 发送邮件
+ ///
+ public async Task SendEmailAsync(SendEmailRequest request)
+ {
+ var account = await _emailAccountRepository.GetByIdAsync(request.EmailAccountId);
+ if (account == null)
+ throw new ArgumentException($"未找到ID为 {request.EmailAccountId} 的邮件账户");
+
+ var message = _mapper.Map(request);
+ message.From = account.EmailAddress;
+
+ return await _emailService.SendEmailAsync(message, account);
+ }
+
+ ///
+ /// 获取所有邮件模板
+ ///
+ public async Task> GetAllEmailTemplatesAsync()
+ {
+ var templates = await _emailTemplateRepository.GetAllAsync();
+ return _mapper.Map>(templates);
+ }
+
+ ///
+ /// 根据ID获取邮件模板
+ ///
+ public async Task GetEmailTemplateByIdAsync(int id)
+ {
+ var template = await _emailTemplateRepository.GetByIdAsync(id);
+ return _mapper.Map(template);
+ }
+
+ ///
+ /// 根据代码获取邮件模板
+ ///
+ public async Task GetEmailTemplateByCodeAsync(string code)
+ {
+ var template = await _emailTemplateRepository.GetByCodeAsync(code);
+ return _mapper.Map(template);
+ }
+
+ ///
+ /// 创建邮件模板
+ ///
+ public async Task CreateEmailTemplateAsync(EmailTemplateDto templateDto)
+ {
+ var template = _mapper.Map(templateDto);
+ var createdTemplate = await _emailTemplateRepository.AddAsync(template);
+ return _mapper.Map(createdTemplate);
+ }
+
+ ///
+ /// 更新邮件模板
+ ///
+ public async Task UpdateEmailTemplateAsync(int id, EmailTemplateDto templateDto)
+ {
+ var existingTemplate = await _emailTemplateRepository.GetByIdAsync(id);
+ if (existingTemplate == null)
+ throw new ArgumentException($"未找到ID为 {id} 的邮件模板");
+
+ _mapper.Map(templateDto, existingTemplate);
+ existingTemplate.UpdatedAt = DateTime.Now;
+
+ var updatedTemplate = await _emailTemplateRepository.UpdateAsync(existingTemplate);
+ return _mapper.Map(existingTemplate);
+ }
+
+ ///
+ /// 删除邮件模板
+ ///
+ public async Task DeleteEmailTemplateAsync(int id)
+ {
+ var template = await _emailTemplateRepository.GetByIdAsync(id);
+ if (template == null)
+ return false;
+
+ await _emailTemplateRepository.DeleteAsync(template);
+ return true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/DMS.Core/Interfaces/Repositories/IEmailAccountRepository.cs b/DMS.Core/Interfaces/Repositories/IEmailAccountRepository.cs
new file mode 100644
index 0000000..9943b4f
--- /dev/null
+++ b/DMS.Core/Interfaces/Repositories/IEmailAccountRepository.cs
@@ -0,0 +1,20 @@
+using DMS.Core.Models;
+
+namespace DMS.Core.Interfaces.Repositories
+{
+ ///
+ /// 邮件账户仓储接口
+ ///
+ public interface IEmailAccountRepository : IBaseRepository
+ {
+ ///
+ /// 获取默认邮件账户
+ ///
+ Task GetDefaultAccountAsync();
+
+ ///
+ /// 获取所有启用的邮件账户
+ ///
+ Task> GetActiveAccountsAsync();
+ }
+}
\ No newline at end of file
diff --git a/DMS.Core/Interfaces/Repositories/IEmailLogRepository.cs b/DMS.Core/Interfaces/Repositories/IEmailLogRepository.cs
new file mode 100644
index 0000000..014e776
--- /dev/null
+++ b/DMS.Core/Interfaces/Repositories/IEmailLogRepository.cs
@@ -0,0 +1,20 @@
+using DMS.Core.Models;
+
+namespace DMS.Core.Interfaces.Repositories
+{
+ ///
+ /// 邮件日志仓储接口
+ ///
+ public interface IEmailLogRepository : IBaseRepository
+ {
+ ///
+ /// 根据邮件消息ID获取日志
+ ///
+ Task> GetByEmailMessageIdAsync(int emailMessageId);
+
+ ///
+ /// 根据日期范围获取日志
+ ///
+ Task> GetByDateRangeAsync(DateTime startDate, DateTime endDate);
+ }
+}
\ No newline at end of file
diff --git a/DMS.Core/Interfaces/Repositories/IEmailMessageRepository.cs b/DMS.Core/Interfaces/Repositories/IEmailMessageRepository.cs
new file mode 100644
index 0000000..fa2852b
--- /dev/null
+++ b/DMS.Core/Interfaces/Repositories/IEmailMessageRepository.cs
@@ -0,0 +1,20 @@
+using DMS.Core.Models;
+
+namespace DMS.Core.Interfaces.Repositories
+{
+ ///
+ /// 邮件消息仓储接口
+ ///
+ public interface IEmailMessageRepository : IBaseRepository
+ {
+ ///
+ /// 根据状态获取邮件消息
+ ///
+ Task> GetByStatusAsync(EmailSendStatus status);
+
+ ///
+ /// 获取指定时间范围内的邮件消息
+ ///
+ Task> GetByDateRangeAsync(DateTime startDate, DateTime endDate);
+ }
+}
\ No newline at end of file
diff --git a/DMS.Core/Interfaces/Repositories/IEmailTemplateRepository.cs b/DMS.Core/Interfaces/Repositories/IEmailTemplateRepository.cs
new file mode 100644
index 0000000..4ee8a4b
--- /dev/null
+++ b/DMS.Core/Interfaces/Repositories/IEmailTemplateRepository.cs
@@ -0,0 +1,20 @@
+using DMS.Core.Models;
+
+namespace DMS.Core.Interfaces.Repositories
+{
+ ///
+ /// 邮件模板仓储接口
+ ///
+ public interface IEmailTemplateRepository : IBaseRepository
+ {
+ ///
+ /// 根据代码获取邮件模板
+ ///
+ Task GetByCodeAsync(string code);
+
+ ///
+ /// 获取所有启用的邮件模板
+ ///
+ Task> GetActiveTemplatesAsync();
+ }
+}
\ No newline at end of file
diff --git a/DMS.Core/Interfaces/Services/IEmailService.cs b/DMS.Core/Interfaces/Services/IEmailService.cs
new file mode 100644
index 0000000..49ba4d1
--- /dev/null
+++ b/DMS.Core/Interfaces/Services/IEmailService.cs
@@ -0,0 +1,33 @@
+using DMS.Core.Models;
+
+namespace DMS.Core.Interfaces.Services
+{
+ ///
+ /// 邮件服务接口
+ ///
+ public interface IEmailService
+ {
+ ///
+ /// 异步发送邮件
+ ///
+ /// 邮件消息
+ /// 邮件账户
+ /// 发送是否成功
+ Task SendEmailAsync(EmailMessage message, EmailAccount account);
+
+ ///
+ /// 异步接收邮件
+ ///
+ /// 邮件账户
+ /// 接收邮件数量
+ /// 接收到的邮件列表
+ Task> ReceiveEmailsAsync(EmailAccount account, int count = 10);
+
+ ///
+ /// 测试邮件账户连接
+ ///
+ /// 邮件账户
+ /// 连接是否成功
+ Task TestConnectionAsync(EmailAccount account);
+ }
+}
\ No newline at end of file
diff --git a/DMS.Core/Models/EmailAccount.cs b/DMS.Core/Models/EmailAccount.cs
new file mode 100644
index 0000000..659b1d6
--- /dev/null
+++ b/DMS.Core/Models/EmailAccount.cs
@@ -0,0 +1,91 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace DMS.Core.Models
+{
+ ///
+ /// 邮件账户配置实体
+ ///
+ public class EmailAccount
+ {
+ ///
+ /// 账户ID
+ ///
+ public int Id { get; set; }
+
+ ///
+ /// 账户名称
+ ///
+ [Required]
+ [MaxLength(100)]
+ public string Name { get; set; }
+
+ ///
+ /// 邮箱地址
+ ///
+ [Required]
+ [MaxLength(255)]
+ public string EmailAddress { get; set; }
+
+ ///
+ /// SMTP服务器地址
+ ///
+ [Required]
+ [MaxLength(100)]
+ public string SmtpServer { get; set; }
+
+ ///
+ /// SMTP端口号
+ ///
+ public int SmtpPort { get; set; } = 587;
+
+ ///
+ /// 是否启用SSL
+ ///
+ public bool EnableSsl { get; set; } = true;
+
+ ///
+ /// 用户名
+ ///
+ [Required]
+ [MaxLength(100)]
+ public string Username { get; set; }
+
+ ///
+ /// 密码
+ ///
+ [Required]
+ [MaxLength(100)]
+ public string Password { get; set; }
+
+ ///
+ /// IMAP服务器地址
+ ///
+ [MaxLength(100)]
+ public string? ImapServer { get; set; }
+
+ ///
+ /// IMAP端口号
+ ///
+ public int ImapPort { get; set; } = 993;
+
+ ///
+ /// 是否为默认账户
+ ///
+ public bool IsDefault { get; set; }
+
+ ///
+ /// 是否启用
+ ///
+ public bool IsActive { get; set; } = true;
+
+ ///
+ /// 创建时间
+ ///
+ public DateTime CreatedAt { get; set; } = DateTime.Now;
+
+ ///
+ /// 更新时间
+ ///
+ public DateTime UpdatedAt { get; set; } = DateTime.Now;
+ }
+}
\ No newline at end of file
diff --git a/DMS.Core/Models/EmailLog.cs b/DMS.Core/Models/EmailLog.cs
new file mode 100644
index 0000000..91449e0
--- /dev/null
+++ b/DMS.Core/Models/EmailLog.cs
@@ -0,0 +1,43 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace DMS.Core.Models
+{
+ ///
+ /// 邮件日志实体
+ ///
+ public class EmailLog
+ {
+ ///
+ /// 日志ID
+ ///
+ public int Id { get; set; }
+
+ ///
+ /// 关联的邮件ID
+ ///
+ public int EmailMessageId { get; set; }
+
+ ///
+ /// 日志级别
+ ///
+ [Required]
+ [MaxLength(20)]
+ public string Level { get; set; }
+
+ ///
+ /// 日志消息
+ ///
+ [Required]
+ public string Message { get; set; }
+
+ ///
+ /// 异常详情
+ ///
+ public string? Exception { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ public DateTime CreatedAt { get; set; } = DateTime.Now;
+ }
+}
\ No newline at end of file
diff --git a/DMS.Core/Models/EmailMessage.cs b/DMS.Core/Models/EmailMessage.cs
new file mode 100644
index 0000000..e31817c
--- /dev/null
+++ b/DMS.Core/Models/EmailMessage.cs
@@ -0,0 +1,105 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace DMS.Core.Models
+{
+ ///
+ /// 邮件消息实体
+ ///
+ public class EmailMessage
+ {
+ ///
+ /// 邮件ID
+ ///
+ public int Id { get; set; }
+
+ ///
+ /// 关联的邮件账户ID
+ ///
+ public int EmailAccountId { get; set; }
+
+ ///
+ /// 发件人邮箱地址
+ ///
+ [Required]
+ [MaxLength(255)]
+ public string From { get; set; }
+
+ ///
+ /// 收件人邮箱地址(多个用分号分隔)
+ ///
+ [Required]
+ [MaxLength(1000)]
+ public string To { get; set; }
+
+ ///
+ /// 抄送邮箱地址(多个用分号分隔)
+ ///
+ [MaxLength(1000)]
+ public string? Cc { get; set; }
+
+ ///
+ /// 密送邮箱地址(多个用分号分隔)
+ ///
+ [MaxLength(1000)]
+ public string? Bcc { get; set; }
+
+ ///
+ /// 邮件主题
+ ///
+ [Required]
+ [MaxLength(500)]
+ public string Subject { get; set; }
+
+ ///
+ /// 邮件正文
+ ///
+ [Required]
+ public string Body { get; set; }
+
+ ///
+ /// 是否为HTML格式
+ ///
+ public bool IsHtml { get; set; } = true;
+
+ ///
+ /// 邮件发送状态
+ ///
+ public EmailSendStatus Status { get; set; } = EmailSendStatus.Pending;
+
+ ///
+ /// 发送时间
+ ///
+ public DateTime? SentAt { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ public DateTime CreatedAt { get; set; } = DateTime.Now;
+
+ ///
+ /// 更新时间
+ ///
+ public DateTime UpdatedAt { get; set; } = DateTime.Now;
+ }
+
+ ///
+ /// 邮件发送状态枚举
+ ///
+ public enum EmailSendStatus
+ {
+ ///
+ /// 待发送
+ ///
+ Pending,
+
+ ///
+ /// 发送成功
+ ///
+ Sent,
+
+ ///
+ /// 发送失败
+ ///
+ Failed
+ }
+}
\ No newline at end of file
diff --git a/DMS.Core/Models/EmailTemplate.cs b/DMS.Core/Models/EmailTemplate.cs
new file mode 100644
index 0000000..bea6c43
--- /dev/null
+++ b/DMS.Core/Models/EmailTemplate.cs
@@ -0,0 +1,62 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace DMS.Core.Models
+{
+ ///
+ /// 邮件模板实体
+ ///
+ public class EmailTemplate
+ {
+ ///
+ /// 模板ID
+ ///
+ public int Id { get; set; }
+
+ ///
+ /// 模板名称
+ ///
+ [Required]
+ [MaxLength(100)]
+ public string Name { get; set; }
+
+ ///
+ /// 模板代码(唯一标识)
+ ///
+ [Required]
+ [MaxLength(50)]
+ public string Code { get; set; }
+
+ ///
+ /// 模板主题
+ ///
+ [Required]
+ [MaxLength(500)]
+ public string Subject { get; set; }
+
+ ///
+ /// 模板内容
+ ///
+ [Required]
+ public string Body { get; set; }
+
+ ///
+ /// 是否为HTML格式
+ ///
+ public bool IsHtml { get; set; } = true;
+
+ ///
+ /// 是否启用
+ ///
+ public bool IsActive { get; set; } = true;
+
+ ///
+ /// 创建时间
+ ///
+ public DateTime CreatedAt { get; set; } = DateTime.Now;
+
+ ///
+ /// 更新时间
+ ///
+ public DateTime UpdatedAt { get; set; } = DateTime.Now;
+ }
+}
\ No newline at end of file
diff --git a/DMS.Infrastructure/DMS.Infrastructure.csproj b/DMS.Infrastructure/DMS.Infrastructure.csproj
index c727733..aab12e8 100644
--- a/DMS.Infrastructure/DMS.Infrastructure.csproj
+++ b/DMS.Infrastructure/DMS.Infrastructure.csproj
@@ -7,6 +7,7 @@
+
diff --git a/DMS.Infrastructure/Entities/DbEmailAccount.cs b/DMS.Infrastructure/Entities/DbEmailAccount.cs
new file mode 100644
index 0000000..3e16347
--- /dev/null
+++ b/DMS.Infrastructure/Entities/DbEmailAccount.cs
@@ -0,0 +1,89 @@
+using SqlSugar;
+using System.ComponentModel.DataAnnotations;
+
+namespace DMS.Infrastructure.Entities
+{
+ ///
+ /// 邮件账户数据库实体
+ ///
+ [SugarTable("email_accounts")]
+ public class DbEmailAccount
+ {
+ ///
+ /// 账户ID
+ ///
+ [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
+ public int Id { get; set; }
+
+ ///
+ /// 账户名称
+ ///
+ [SugarColumn(Length = 100)]
+ public string Name { get; set; }
+
+ ///
+ /// 邮箱地址
+ ///
+ [SugarColumn(Length = 255)]
+ public string EmailAddress { get; set; }
+
+ ///
+ /// SMTP服务器地址
+ ///
+ [SugarColumn(Length = 100)]
+ public string SmtpServer { get; set; }
+
+ ///
+ /// SMTP端口号
+ ///
+ public int SmtpPort { get; set; } = 587;
+
+ ///
+ /// 是否启用SSL
+ ///
+ public bool EnableSsl { get; set; } = true;
+
+ ///
+ /// 用户名
+ ///
+ [SugarColumn(Length = 100)]
+ public string Username { get; set; }
+
+ ///
+ /// 密码
+ ///
+ [SugarColumn(Length = 100)]
+ public string Password { get; set; }
+
+ ///
+ /// IMAP服务器地址
+ ///
+ [SugarColumn(Length = 100, IsNullable = true)]
+ public string? ImapServer { get; set; }
+
+ ///
+ /// IMAP端口号
+ ///
+ public int ImapPort { get; set; } = 993;
+
+ ///
+ /// 是否为默认账户
+ ///
+ public bool IsDefault { get; set; }
+
+ ///
+ /// 是否启用
+ ///
+ public bool IsActive { get; set; } = true;
+
+ ///
+ /// 创建时间
+ ///
+ public DateTime CreatedAt { get; set; } = DateTime.Now;
+
+ ///
+ /// 更新时间
+ ///
+ public DateTime UpdatedAt { get; set; } = DateTime.Now;
+ }
+}
\ No newline at end of file
diff --git a/DMS.Infrastructure/Entities/DbEmailLog.cs b/DMS.Infrastructure/Entities/DbEmailLog.cs
new file mode 100644
index 0000000..75576b4
--- /dev/null
+++ b/DMS.Infrastructure/Entities/DbEmailLog.cs
@@ -0,0 +1,46 @@
+using SqlSugar;
+using System.ComponentModel.DataAnnotations;
+
+namespace DMS.Infrastructure.Entities
+{
+ ///
+ /// 邮件日志数据库实体
+ ///
+ [SugarTable("email_logs")]
+ public class DbEmailLog
+ {
+ ///
+ /// 日志ID
+ ///
+ [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
+ public int Id { get; set; }
+
+ ///
+ /// 关联的邮件ID
+ ///
+ public int EmailMessageId { get; set; }
+
+ ///
+ /// 日志级别
+ ///
+ [SugarColumn(Length = 20)]
+ public string Level { get; set; }
+
+ ///
+ /// 日志消息
+ ///
+ [SugarColumn(Length = 4000)]
+ public string Message { get; set; }
+
+ ///
+ /// 异常详情
+ ///
+ [SugarColumn(Length = 2000, IsNullable = true)]
+ public string? Exception { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ public DateTime CreatedAt { get; set; } = DateTime.Now;
+ }
+}
\ No newline at end of file
diff --git a/DMS.Infrastructure/Entities/DbEmailMessage.cs b/DMS.Infrastructure/Entities/DbEmailMessage.cs
new file mode 100644
index 0000000..8a0ba1d
--- /dev/null
+++ b/DMS.Infrastructure/Entities/DbEmailMessage.cs
@@ -0,0 +1,86 @@
+using SqlSugar;
+using System.ComponentModel.DataAnnotations;
+
+namespace DMS.Infrastructure.Entities
+{
+ ///
+ /// 邮件消息数据库实体
+ ///
+ [SugarTable("email_messages")]
+ public class DbEmailMessage
+ {
+ ///
+ /// 邮件ID
+ ///
+ [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
+ public int Id { get; set; }
+
+ ///
+ /// 关联的邮件账户ID
+ ///
+ public int EmailAccountId { get; set; }
+
+ ///
+ /// 发件人邮箱地址
+ ///
+ [SugarColumn(Length = 255)]
+ public string From { get; set; }
+
+ ///
+ /// 收件人邮箱地址(多个用分号分隔)
+ ///
+ [SugarColumn(Length = 1000)]
+ public string To { get; set; }
+
+ ///
+ /// 抄送邮箱地址(多个用分号分隔)
+ ///
+ [SugarColumn(Length = 1000, IsNullable = true)]
+ public string? Cc { get; set; }
+
+ ///
+ /// 密送邮箱地址(多个用分号分隔)
+ ///
+ [SugarColumn(Length = 1000, IsNullable = true)]
+ public string? Bcc { get; set; }
+
+ ///
+ /// 邮件主题
+ ///
+ [SugarColumn(Length = 500)]
+ public string Subject { get; set; }
+
+ ///
+ /// 邮件正文
+ ///
+ [SugarColumn(Length = 4000)]
+ public string Body { get; set; }
+
+ ///
+ /// 是否为HTML格式
+ ///
+ public bool IsHtml { get; set; } = true;
+
+ ///
+ /// 邮件发送状态
+ ///
+ [SugarColumn(Length = 20)]
+ public string Status { get; set; } = "Pending";
+
+ ///
+ /// 发送时间
+ ///
+ [SugarColumn(IsNullable = true)]
+ public DateTime? SentAt { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ public DateTime CreatedAt { get; set; } = DateTime.Now;
+
+ ///
+ /// 更新时间
+ ///
+ public DateTime UpdatedAt { get; set; } = DateTime.Now;
+ }
+}
\ No newline at end of file
diff --git a/DMS.Infrastructure/Entities/DbEmailTemplate.cs b/DMS.Infrastructure/Entities/DbEmailTemplate.cs
new file mode 100644
index 0000000..8d5e97e
--- /dev/null
+++ b/DMS.Infrastructure/Entities/DbEmailTemplate.cs
@@ -0,0 +1,62 @@
+using SqlSugar;
+using System.ComponentModel.DataAnnotations;
+
+namespace DMS.Infrastructure.Entities
+{
+ ///
+ /// 邮件模板数据库实体
+ ///
+ [SugarTable("email_templates")]
+ public class DbEmailTemplate
+ {
+ ///
+ /// 模板ID
+ ///
+ [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
+ public int Id { get; set; }
+
+ ///
+ /// 模板名称
+ ///
+ [SugarColumn(Length = 100)]
+ public string Name { get; set; }
+
+ ///
+ /// 模板代码(唯一标识)
+ ///
+ [SugarColumn(Length = 50)]
+ public string Code { get; set; }
+
+ ///
+ /// 模板主题
+ ///
+ [SugarColumn(Length = 500)]
+ public string Subject { get; set; }
+
+ ///
+ /// 模板内容
+ ///
+ [SugarColumn(Length = 4000)]
+ public string Body { get; set; }
+
+ ///
+ /// 是否为HTML格式
+ ///
+ public bool IsHtml { get; set; } = true;
+
+ ///
+ /// 是否启用
+ ///
+ public bool IsActive { get; set; } = true;
+
+ ///
+ /// 创建时间
+ ///
+ public DateTime CreatedAt { get; set; } = DateTime.Now;
+
+ ///
+ /// 更新时间
+ ///
+ public DateTime UpdatedAt { get; set; } = DateTime.Now;
+ }
+}
\ No newline at end of file
diff --git a/DMS.Infrastructure/Profiles/MappingProfile.cs b/DMS.Infrastructure/Profiles/MappingProfile.cs
index 9d313e1..84bbf91 100644
--- a/DMS.Infrastructure/Profiles/MappingProfile.cs
+++ b/DMS.Infrastructure/Profiles/MappingProfile.cs
@@ -37,5 +37,10 @@ public class MappingProfile : Profile
CreateMap().ReverseMap();
CreateMap().ReverseMap();
+
+ CreateMap().ReverseMap();
+ CreateMap().ReverseMap();
+ CreateMap().ReverseMap();
+ CreateMap().ReverseMap();
}
}
diff --git a/DMS.Infrastructure/Repositories/EmailAccountRepository.cs b/DMS.Infrastructure/Repositories/EmailAccountRepository.cs
new file mode 100644
index 0000000..d92801d
--- /dev/null
+++ b/DMS.Infrastructure/Repositories/EmailAccountRepository.cs
@@ -0,0 +1,158 @@
+using AutoMapper;
+using DMS.Core.Interfaces.Repositories;
+using DMS.Core.Models;
+using DMS.Infrastructure.Data;
+using DMS.Infrastructure.Entities;
+using Microsoft.Extensions.Logging;
+using SqlSugar;
+
+namespace DMS.Infrastructure.Repositories
+{
+ ///
+ /// 邮件账户仓储实现
+ ///
+ public class EmailAccountRepository : IEmailAccountRepository
+ {
+ private readonly SqlSugarDbContext _dbContext;
+ protected readonly ILogger _logger;
+ private readonly IMapper _mapper;
+
+ public EmailAccountRepository(IMapper mapper, SqlSugarDbContext dbContext, ILogger logger)
+ {
+ _mapper = mapper;
+ _dbContext = dbContext;
+ _logger = logger;
+ }
+
+ ///
+ /// 获取 SqlSugarClient 实例
+ ///
+ protected SqlSugarClient Db
+ {
+ get { return _dbContext.GetInstance(); }
+ }
+
+ ///
+ /// 获取默认邮件账户
+ ///
+ public async Task GetDefaultAccountAsync()
+ {
+ var dbEntity = await Db.Queryable()
+ .Where(e => e.IsDefault && e.IsActive)
+ .FirstAsync();
+
+ return dbEntity != null ? _mapper.Map(dbEntity) : null;
+ }
+
+ ///
+ /// 获取所有启用的邮件账户
+ ///
+ public async Task> GetActiveAccountsAsync()
+ {
+ var dbEntities = await Db.Queryable()
+ .Where(e => e.IsActive)
+ .ToListAsync();
+
+ return _mapper.Map>(dbEntities);
+ }
+
+ ///
+ /// 异步根据ID获取单个实体。
+ ///
+ public async Task GetByIdAsync(int id)
+ {
+ var dbEntity = await Db.Queryable()
+ .In(id)
+ .FirstAsync();
+
+ return dbEntity != null ? _mapper.Map(dbEntity) : null;
+ }
+
+ ///
+ /// 异步获取所有实体。
+ ///
+ public async Task> GetAllAsync()
+ {
+ var dbEntities = await Db.Queryable()
+ .ToListAsync();
+
+ return _mapper.Map>(dbEntities);
+ }
+
+ ///
+ /// 异步添加一个新实体。
+ ///
+ public async Task AddAsync(EmailAccount entity)
+ {
+ var dbEntity = _mapper.Map(entity);
+ var result = await Db.Insertable(dbEntity)
+ .ExecuteReturnEntityAsync();
+
+ return _mapper.Map(result);
+ }
+
+ ///
+ /// 异步更新一个已存在的实体。
+ ///
+ public async Task UpdateAsync(EmailAccount entity)
+ {
+ var dbEntity = _mapper.Map(entity);
+ return await Db.Updateable(dbEntity)
+ .ExecuteCommandAsync();
+ }
+
+ ///
+ /// 异步根据ID删除一个实体。
+ ///
+ public async Task DeleteAsync(EmailAccount entity)
+ {
+ var dbEntity = _mapper.Map(entity);
+ return await Db.Deleteable(dbEntity)
+ .ExecuteCommandAsync();
+ }
+
+ ///
+ /// 异步根据ID删除一个实体。
+ ///
+ public async Task DeleteByIdAsync(int id)
+ {
+ return await Db.Deleteable()
+ .In(id)
+ .ExecuteCommandAsync();
+ }
+
+ ///
+ /// 异步根据ID列表批量删除实体。
+ ///
+ public async Task DeleteByIdsAsync(List ids)
+ {
+ return await Db.Deleteable()
+ .In(ids)
+ .ExecuteCommandAsync();
+ }
+
+ ///
+ /// 从数据库获取数据。
+ ///
+ public async Task> TakeAsync(int number)
+ {
+ var dbEntities = await Db.Queryable()
+ .Take(number)
+ .ToListAsync();
+
+ return _mapper.Map>(dbEntities);
+ }
+
+ ///
+ /// 异步批量添加实体。
+ ///
+ public async Task AddBatchAsync(List entities)
+ {
+ var dbEntities = _mapper.Map>(entities);
+ var result = await Db.Insertable(dbEntities)
+ .ExecuteCommandAsync();
+
+ return result > 0;
+ }
+ }
+}
\ No newline at end of file
diff --git a/DMS.Infrastructure/Repositories/EmailLogRepository.cs b/DMS.Infrastructure/Repositories/EmailLogRepository.cs
new file mode 100644
index 0000000..ad61c0b
--- /dev/null
+++ b/DMS.Infrastructure/Repositories/EmailLogRepository.cs
@@ -0,0 +1,158 @@
+using AutoMapper;
+using DMS.Core.Interfaces.Repositories;
+using DMS.Core.Models;
+using DMS.Infrastructure.Data;
+using DMS.Infrastructure.Entities;
+using Microsoft.Extensions.Logging;
+using SqlSugar;
+
+namespace DMS.Infrastructure.Repositories
+{
+ ///
+ /// 邮件日志仓储实现
+ ///
+ public class EmailLogRepository : IEmailLogRepository
+ {
+ private readonly SqlSugarDbContext _dbContext;
+ protected readonly ILogger _logger;
+ private readonly IMapper _mapper;
+
+ public EmailLogRepository(IMapper mapper, SqlSugarDbContext dbContext, ILogger logger)
+ {
+ _mapper = mapper;
+ _dbContext = dbContext;
+ _logger = logger;
+ }
+
+ ///
+ /// 获取 SqlSugarClient 实例
+ ///
+ protected SqlSugarClient Db
+ {
+ get { return _dbContext.GetInstance(); }
+ }
+
+ ///
+ /// 异步根据ID获取单个实体。
+ ///
+ public async Task GetByIdAsync(int id)
+ {
+ var dbEntity = await Db.Queryable()
+ .In(id)
+ .FirstAsync();
+
+ return dbEntity != null ? _mapper.Map(dbEntity) : null;
+ }
+
+ ///
+ /// 异步获取所有实体。
+ ///
+ public async Task> GetAllAsync()
+ {
+ var dbEntities = await Db.Queryable()
+ .ToListAsync();
+
+ return _mapper.Map>(dbEntities);
+ }
+
+ ///
+ /// 异步添加一个新实体。
+ ///
+ public async Task AddAsync(EmailLog entity)
+ {
+ var dbEntity = _mapper.Map(entity);
+ var result = await Db.Insertable(dbEntity)
+ .ExecuteReturnEntityAsync();
+
+ return _mapper.Map(result);
+ }
+
+ ///
+ /// 异步更新一个已存在的实体。
+ ///
+ public async Task UpdateAsync(EmailLog entity)
+ {
+ var dbEntity = _mapper.Map(entity);
+ return await Db.Updateable(dbEntity)
+ .ExecuteCommandAsync();
+ }
+
+ ///
+ /// 异步根据ID删除一个实体。
+ ///
+ public async Task DeleteAsync(EmailLog entity)
+ {
+ var dbEntity = _mapper.Map(entity);
+ return await Db.Deleteable(dbEntity)
+ .ExecuteCommandAsync();
+ }
+
+ ///
+ /// 异步根据ID删除一个实体。
+ ///
+ public async Task DeleteByIdAsync(int id)
+ {
+ return await Db.Deleteable()
+ .In(id)
+ .ExecuteCommandAsync();
+ }
+
+ ///
+ /// 异步根据ID列表批量删除实体。
+ ///
+ public async Task DeleteByIdsAsync(List ids)
+ {
+ return await Db.Deleteable()
+ .In(ids)
+ .ExecuteCommandAsync();
+ }
+
+ ///
+ /// 从数据库获取数据。
+ ///
+ public async Task> TakeAsync(int number)
+ {
+ var dbEntities = await Db.Queryable()
+ .Take(number)
+ .ToListAsync();
+
+ return _mapper.Map>(dbEntities);
+ }
+
+ ///
+ /// 异步批量添加实体。
+ ///
+ public async Task AddBatchAsync(List entities)
+ {
+ var dbEntities = _mapper.Map>(entities);
+ var result = await Db.Insertable(dbEntities)
+ .ExecuteCommandAsync();
+
+ return result > 0;
+ }
+
+ ///
+ /// 根据邮件消息ID获取日志
+ ///
+ public async Task> GetByEmailMessageIdAsync(int emailMessageId)
+ {
+ var dbEntities = await Db.Queryable()
+ .Where(e => e.EmailMessageId == emailMessageId)
+ .ToListAsync();
+
+ return _mapper.Map>(dbEntities);
+ }
+
+ ///
+ /// 根据日期范围获取日志
+ ///
+ public async Task> GetByDateRangeAsync(DateTime startDate, DateTime endDate)
+ {
+ var dbEntities = await Db.Queryable()
+ .Where(e => e.CreatedAt >= startDate && e.CreatedAt <= endDate)
+ .ToListAsync();
+
+ return _mapper.Map>(dbEntities);
+ }
+ }
+}
\ No newline at end of file
diff --git a/DMS.Infrastructure/Repositories/EmailMessageRepository.cs b/DMS.Infrastructure/Repositories/EmailMessageRepository.cs
new file mode 100644
index 0000000..4f98dbe
--- /dev/null
+++ b/DMS.Infrastructure/Repositories/EmailMessageRepository.cs
@@ -0,0 +1,158 @@
+using AutoMapper;
+using DMS.Core.Interfaces.Repositories;
+using DMS.Core.Models;
+using DMS.Infrastructure.Data;
+using DMS.Infrastructure.Entities;
+using Microsoft.Extensions.Logging;
+using SqlSugar;
+
+namespace DMS.Infrastructure.Repositories
+{
+ ///
+ /// 邮件消息仓储实现
+ ///
+ public class EmailMessageRepository : IEmailMessageRepository
+ {
+ private readonly SqlSugarDbContext _dbContext;
+ protected readonly ILogger _logger;
+ private readonly IMapper _mapper;
+
+ public EmailMessageRepository(IMapper mapper, SqlSugarDbContext dbContext, ILogger logger)
+ {
+ _mapper = mapper;
+ _dbContext = dbContext;
+ _logger = logger;
+ }
+
+ ///
+ /// 获取 SqlSugarClient 实例
+ ///
+ protected SqlSugarClient Db
+ {
+ get { return _dbContext.GetInstance(); }
+ }
+
+ ///
+ /// 异步根据ID获取单个实体。
+ ///
+ public async Task GetByIdAsync(int id)
+ {
+ var dbEntity = await Db.Queryable()
+ .In(id)
+ .FirstAsync();
+
+ return dbEntity != null ? _mapper.Map(dbEntity) : null;
+ }
+
+ ///
+ /// 异步获取所有实体。
+ ///
+ public async Task> GetAllAsync()
+ {
+ var dbEntities = await Db.Queryable()
+ .ToListAsync();
+
+ return _mapper.Map>(dbEntities);
+ }
+
+ ///
+ /// 异步添加一个新实体。
+ ///
+ public async Task AddAsync(EmailMessage entity)
+ {
+ var dbEntity = _mapper.Map(entity);
+ var result = await Db.Insertable(dbEntity)
+ .ExecuteReturnEntityAsync();
+
+ return _mapper.Map(result);
+ }
+
+ ///
+ /// 异步更新一个已存在的实体。
+ ///
+ public async Task UpdateAsync(EmailMessage entity)
+ {
+ var dbEntity = _mapper.Map(entity);
+ return await Db.Updateable(dbEntity)
+ .ExecuteCommandAsync();
+ }
+
+ ///
+ /// 异步根据ID删除一个实体。
+ ///
+ public async Task DeleteAsync(EmailMessage entity)
+ {
+ var dbEntity = _mapper.Map(entity);
+ return await Db.Deleteable(dbEntity)
+ .ExecuteCommandAsync();
+ }
+
+ ///
+ /// 异步根据ID删除一个实体。
+ ///
+ public async Task DeleteByIdAsync(int id)
+ {
+ return await Db.Deleteable()
+ .In(id)
+ .ExecuteCommandAsync();
+ }
+
+ ///
+ /// 异步根据ID列表批量删除实体。
+ ///
+ public async Task DeleteByIdsAsync(List ids)
+ {
+ return await Db.Deleteable()
+ .In(ids)
+ .ExecuteCommandAsync();
+ }
+
+ ///
+ /// 从数据库获取数据。
+ ///
+ public async Task> TakeAsync(int number)
+ {
+ var dbEntities = await Db.Queryable()
+ .Take(number)
+ .ToListAsync();
+
+ return _mapper.Map>(dbEntities);
+ }
+
+ ///
+ /// 异步批量添加实体。
+ ///
+ public async Task AddBatchAsync(List entities)
+ {
+ var dbEntities = _mapper.Map>(entities);
+ var result = await Db.Insertable(dbEntities)
+ .ExecuteCommandAsync();
+
+ return result > 0;
+ }
+
+ ///
+ /// 根据状态获取邮件消息
+ ///
+ public async Task> GetByStatusAsync(EmailSendStatus status)
+ {
+ var dbEntities = await Db.Queryable()
+ .Where(e => e.Status == status.ToString())
+ .ToListAsync();
+
+ return _mapper.Map>(dbEntities);
+ }
+
+ ///
+ /// 获取指定时间范围内的邮件消息
+ ///
+ public async Task> GetByDateRangeAsync(DateTime startDate, DateTime endDate)
+ {
+ var dbEntities = await Db.Queryable()
+ .Where(e => e.CreatedAt >= startDate && e.CreatedAt <= endDate)
+ .ToListAsync();
+
+ return _mapper.Map>(dbEntities);
+ }
+ }
+}
\ No newline at end of file
diff --git a/DMS.Infrastructure/Repositories/EmailTemplateRepository.cs b/DMS.Infrastructure/Repositories/EmailTemplateRepository.cs
new file mode 100644
index 0000000..b96af4a
--- /dev/null
+++ b/DMS.Infrastructure/Repositories/EmailTemplateRepository.cs
@@ -0,0 +1,158 @@
+using AutoMapper;
+using DMS.Core.Interfaces.Repositories;
+using DMS.Core.Models;
+using DMS.Infrastructure.Data;
+using DMS.Infrastructure.Entities;
+using Microsoft.Extensions.Logging;
+using SqlSugar;
+
+namespace DMS.Infrastructure.Repositories
+{
+ ///
+ /// 邮件模板仓储实现
+ ///
+ public class EmailTemplateRepository : IEmailTemplateRepository
+ {
+ private readonly SqlSugarDbContext _dbContext;
+ protected readonly ILogger _logger;
+ private readonly IMapper _mapper;
+
+ public EmailTemplateRepository(IMapper mapper, SqlSugarDbContext dbContext, ILogger logger)
+ {
+ _mapper = mapper;
+ _dbContext = dbContext;
+ _logger = logger;
+ }
+
+ ///
+ /// 获取 SqlSugarClient 实例
+ ///
+ protected SqlSugarClient Db
+ {
+ get { return _dbContext.GetInstance(); }
+ }
+
+ ///
+ /// 异步根据ID获取单个实体。
+ ///
+ public async Task GetByIdAsync(int id)
+ {
+ var dbEntity = await Db.Queryable()
+ .In(id)
+ .FirstAsync();
+
+ return dbEntity != null ? _mapper.Map(dbEntity) : null;
+ }
+
+ ///
+ /// 异步获取所有实体。
+ ///
+ public async Task> GetAllAsync()
+ {
+ var dbEntities = await Db.Queryable()
+ .ToListAsync();
+
+ return _mapper.Map>(dbEntities);
+ }
+
+ ///
+ /// 异步添加一个新实体。
+ ///
+ public async Task AddAsync(EmailTemplate entity)
+ {
+ var dbEntity = _mapper.Map(entity);
+ var result = await Db.Insertable(dbEntity)
+ .ExecuteReturnEntityAsync();
+
+ return _mapper.Map(result);
+ }
+
+ ///
+ /// 异步更新一个已存在的实体。
+ ///
+ public async Task UpdateAsync(EmailTemplate entity)
+ {
+ var dbEntity = _mapper.Map(entity);
+ return await Db.Updateable(dbEntity)
+ .ExecuteCommandAsync();
+ }
+
+ ///
+ /// 异步根据ID删除一个实体。
+ ///
+ public async Task DeleteAsync(EmailTemplate entity)
+ {
+ var dbEntity = _mapper.Map(entity);
+ return await Db.Deleteable(dbEntity)
+ .ExecuteCommandAsync();
+ }
+
+ ///
+ /// 异步根据ID删除一个实体。
+ ///
+ public async Task DeleteByIdAsync(int id)
+ {
+ return await Db.Deleteable()
+ .In(id)
+ .ExecuteCommandAsync();
+ }
+
+ ///
+ /// 异步根据ID列表批量删除实体。
+ ///
+ public async Task DeleteByIdsAsync(List ids)
+ {
+ return await Db.Deleteable()
+ .In(ids)
+ .ExecuteCommandAsync();
+ }
+
+ ///
+ /// 从数据库获取数据。
+ ///
+ public async Task> TakeAsync(int number)
+ {
+ var dbEntities = await Db.Queryable()
+ .Take(number)
+ .ToListAsync();
+
+ return _mapper.Map>(dbEntities);
+ }
+
+ ///
+ /// 异步批量添加实体。
+ ///
+ public async Task AddBatchAsync(List entities)
+ {
+ var dbEntities = _mapper.Map>(entities);
+ var result = await Db.Insertable(dbEntities)
+ .ExecuteCommandAsync();
+
+ return result > 0;
+ }
+
+ ///
+ /// 根据代码获取邮件模板
+ ///
+ public async Task GetByCodeAsync(string code)
+ {
+ var dbEntity = await Db.Queryable()
+ .Where(e => e.Code == code && e.IsActive)
+ .FirstAsync();
+
+ return dbEntity != null ? _mapper.Map(dbEntity) : null;
+ }
+
+ ///
+ /// 获取所有启用的邮件模板
+ ///
+ public async Task> GetActiveTemplatesAsync()
+ {
+ var dbEntities = await Db.Queryable()
+ .Where(e => e.IsActive)
+ .ToListAsync();
+
+ return _mapper.Map>(dbEntities);
+ }
+ }
+}
\ No newline at end of file
diff --git a/DMS.Infrastructure/Repositories/InitializeRepository.cs b/DMS.Infrastructure/Repositories/InitializeRepository.cs
index fa88cf3..a1d5c65 100644
--- a/DMS.Infrastructure/Repositories/InitializeRepository.cs
+++ b/DMS.Infrastructure/Repositories/InitializeRepository.cs
@@ -46,6 +46,11 @@ public class InitializeRepository : IInitializeRepository
_db.CodeFirst.InitTables();
_db.CodeFirst.InitTables();
_db.CodeFirst.InitTables();
+ _db.CodeFirst.InitTables();
+ _db.CodeFirst.InitTables();
+ _db.CodeFirst.InitTables();
+ _db.CodeFirst.InitTables();
+ _db.CodeFirst.InitTables();
}
///
@@ -140,14 +145,20 @@ public class InitializeRepository : IInitializeRepository
},
new DbMenu
{
- Id = 6, Header = "设置", Icon = "\uE713", ParentId = 0,
- MenuType = MenuType.MainMenu, TargetViewKey = "SettingView",
+ Id = 6, Header = "邮件管理", Icon = "\uE715", ParentId = 0,
+ MenuType = MenuType.MainMenu, TargetViewKey = "EmailManagementView",
DisplayOrder = 6
},
new DbMenu
{
- Id = 7, Header = "关于", Icon = "\uE946", ParentId = 0,
- MenuType = MenuType.MainMenu, TargetViewKey = "", DisplayOrder = 7
+ Id = 7, Header = "设置", Icon = "\uE713", ParentId = 0,
+ MenuType = MenuType.MainMenu, TargetViewKey = "SettingView",
+ DisplayOrder = 7
+ },
+ new DbMenu
+ {
+ Id = 8, Header = "关于", Icon = "\uE946", ParentId = 0,
+ MenuType = MenuType.MainMenu, TargetViewKey = "", DisplayOrder = 8
} // 假设有一个AboutView
};
diff --git a/DMS.Infrastructure/Services/EmailService.cs b/DMS.Infrastructure/Services/EmailService.cs
new file mode 100644
index 0000000..f8acf29
--- /dev/null
+++ b/DMS.Infrastructure/Services/EmailService.cs
@@ -0,0 +1,170 @@
+using DMS.Core.Interfaces.Services;
+using DMS.Core.Models;
+using MailKit.Net.Imap;
+using MailKit.Net.Smtp;
+using MailKit.Security;
+using Microsoft.Extensions.Logging;
+using MimeKit;
+
+namespace DMS.Infrastructure.Services
+{
+ ///
+ /// 邮件服务实现
+ ///
+ public class EmailService : IEmailService
+ {
+ private readonly ILogger _logger;
+
+ public EmailService(ILogger logger)
+ {
+ _logger = logger;
+ }
+
+ ///
+ /// 异步发送邮件
+ ///
+ public async Task SendEmailAsync(EmailMessage message, EmailAccount account)
+ {
+ try
+ {
+ var mimeMessage = new MimeMessage();
+ mimeMessage.From.Add(new MailboxAddress(account.EmailAddress, account.EmailAddress));
+ mimeMessage.To.AddRange(ParseAddresses(message.To));
+
+ if (!string.IsNullOrEmpty(message.Cc))
+ mimeMessage.Cc.AddRange(ParseAddresses(message.Cc));
+
+ if (!string.IsNullOrEmpty(message.Bcc))
+ mimeMessage.Bcc.AddRange(ParseAddresses(message.Bcc));
+
+ mimeMessage.Subject = message.Subject;
+
+ var bodyBuilder = new BodyBuilder();
+ if (message.IsHtml)
+ bodyBuilder.HtmlBody = message.Body;
+ else
+ bodyBuilder.TextBody = message.Body;
+
+ mimeMessage.Body = bodyBuilder.ToMessageBody();
+
+ using var client = new SmtpClient();
+ await client.ConnectAsync(account.SmtpServer, account.SmtpPort, account.EnableSsl ? SecureSocketOptions.SslOnConnect : SecureSocketOptions.None);
+ await client.AuthenticateAsync(account.Username, account.Password);
+ await client.SendAsync(mimeMessage);
+ await client.DisconnectAsync(true);
+
+ message.Status = EmailSendStatus.Sent;
+ message.SentAt = DateTime.Now;
+
+ _logger.LogInformation($"邮件发送成功: {message.Subject}");
+ return true;
+ }
+ catch (Exception ex)
+ {
+ message.Status = EmailSendStatus.Failed;
+ _logger.LogError(ex, $"邮件发送失败: {message.Subject}");
+ return false;
+ }
+ }
+
+ ///
+ /// 异步接收邮件
+ ///
+ public async Task> ReceiveEmailsAsync(EmailAccount account, int count = 10)
+ {
+ var emails = new List();
+
+ try
+ {
+ if (string.IsNullOrEmpty(account.ImapServer))
+ {
+ _logger.LogWarning("未配置IMAP服务器,无法接收邮件");
+ return emails;
+ }
+
+ using var client = new ImapClient();
+ await client.ConnectAsync(account.ImapServer, account.ImapPort, SecureSocketOptions.SslOnConnect);
+ await client.AuthenticateAsync(account.Username, account.Password);
+
+ var inbox = client.Inbox;
+ await inbox.OpenAsync(MailKit.FolderAccess.ReadOnly);
+
+ var endIndex = Math.Min(count, inbox.Count);
+ for (int i = 0; i < endIndex; i++)
+ {
+ var message = await inbox.GetMessageAsync(i);
+ var email = new EmailMessage
+ {
+ EmailAccountId = account.Id,
+ From = message.From.ToString(),
+ To = message.To.ToString(),
+ Subject = message.Subject,
+ Body = message.TextBody ?? message.HtmlBody ?? "",
+ IsHtml = !string.IsNullOrEmpty(message.HtmlBody),
+ SentAt = message.Date.DateTime,
+ CreatedAt = DateTime.Now,
+ UpdatedAt = DateTime.Now
+ };
+ emails.Add(email);
+ }
+
+ await client.DisconnectAsync(true);
+ _logger.LogInformation($"成功接收 {emails.Count} 封邮件");
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "接收邮件时发生错误");
+ }
+
+ return emails;
+ }
+
+ ///
+ /// 测试邮件账户连接
+ ///
+ public async Task TestConnectionAsync(EmailAccount account)
+ {
+ try
+ {
+ // 测试SMTP连接
+ using var smtpClient = new SmtpClient();
+ await smtpClient.ConnectAsync(account.SmtpServer, account.SmtpPort, account.EnableSsl ? SecureSocketOptions.SslOnConnect : SecureSocketOptions.None);
+ await smtpClient.AuthenticateAsync(account.Username, account.Password);
+ await smtpClient.DisconnectAsync(true);
+
+ // 如果配置了IMAP服务器,也测试IMAP连接
+ if (!string.IsNullOrEmpty(account.ImapServer))
+ {
+ using var imapClient = new ImapClient();
+ await imapClient.ConnectAsync(account.ImapServer, account.ImapPort, SecureSocketOptions.SslOnConnect);
+ await imapClient.AuthenticateAsync(account.Username, account.Password);
+ await imapClient.DisconnectAsync(true);
+ }
+
+ _logger.LogInformation($"邮件账户 {account.EmailAddress} 连接测试成功");
+ return true;
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, $"邮件账户 {account.EmailAddress} 连接测试失败");
+ return false;
+ }
+ }
+
+ ///
+ /// 解析邮箱地址字符串
+ ///
+ private IEnumerable ParseAddresses(string addresses)
+ {
+ var addressList = addresses.Split(new[] { ';', ',' }, StringSplitOptions.RemoveEmptyEntries);
+ foreach (var address in addressList)
+ {
+ var trimmedAddress = address.Trim();
+ if (!string.IsNullOrEmpty(trimmedAddress))
+ {
+ yield return MailboxAddress.Parse(trimmedAddress);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/DMS.WPF/App.xaml.cs b/DMS.WPF/App.xaml.cs
index c30663f..e205a05 100644
--- a/DMS.WPF/App.xaml.cs
+++ b/DMS.WPF/App.xaml.cs
@@ -216,11 +216,16 @@ public partial class App : System.Windows.Application
services.AddSingleton();
services.AddSingleton();
services.AddSingleton(); // 添加这行
+ services.AddSingleton();
+ services.AddSingleton();
+ services.AddSingleton();
+ services.AddSingleton();
services.AddSingleton();
services.AddTransient();
services.AddTransient();
services.AddTransient();
+ services.AddTransient();
// 注册App服务\r\n
services.AddSingleton();
@@ -267,6 +272,8 @@ public partial class App : System.Windows.Application
// 注册主数据服务
services.AddSingleton();
+ services.AddSingleton();
+ services.AddSingleton();
// 注册视图模型
@@ -283,6 +290,7 @@ public partial class App : System.Windows.Application
services.AddSingleton();
services.AddScoped();
services.AddSingleton();
+ services.AddSingleton();
// 注册对话框视图模型
services.AddTransient();
@@ -298,6 +306,8 @@ public partial class App : System.Windows.Application
services.AddTransient();
services.AddTransient();
services.AddTransient();
+ services.AddTransient();
+ services.AddTransient();
// 注册View视图
services.AddSingleton();
@@ -310,6 +320,8 @@ public partial class App : System.Windows.Application
services.AddSingleton();
services.AddScoped();
services.AddScoped();
+ services.AddSingleton();
+
}
private void ConfigureLogging(ILoggingBuilder loggingBuilder)
diff --git a/DMS.WPF/Interfaces/IDialogViewModel.cs b/DMS.WPF/Interfaces/IDialogViewModel.cs
new file mode 100644
index 0000000..30df0fb
--- /dev/null
+++ b/DMS.WPF/Interfaces/IDialogViewModel.cs
@@ -0,0 +1,13 @@
+namespace DMS.WPF.Interfaces
+{
+ ///
+ /// 对话框视图模型接口
+ ///
+ public interface IDialogViewModel
+ {
+ ///
+ /// 关闭请求事件
+ ///
+ event Action CloseRequested;
+ }
+}
\ No newline at end of file
diff --git a/DMS.WPF/Services/DialogService.cs b/DMS.WPF/Services/DialogService.cs
index bb49052..0d70457 100644
--- a/DMS.WPF/Services/DialogService.cs
+++ b/DMS.WPF/Services/DialogService.cs
@@ -27,7 +27,8 @@ namespace DMS.WPF.Services
{ typeof(MqttSelectionDialogViewModel), typeof(MqttSelectionDialog) },
{ typeof(MqttAliasBatchEditDialogViewModel), typeof(MqttAliasBatchEditDialog) },
{ typeof(HistorySettingsDialogViewModel), typeof(HistorySettingsDialog) },
- { typeof(AlarmSettingsDialogViewModel), typeof(AlarmSettingsDialog) }
+ { typeof(AlarmSettingsDialogViewModel), typeof(AlarmSettingsDialog) },
+ { typeof(EmailAccountDialogViewModel), typeof(EmailAccountDialog) }
// Add other mappings here
// ... other dialogs
};
diff --git a/DMS.WPF/Services/EmailFunctionalityTestService.cs b/DMS.WPF/Services/EmailFunctionalityTestService.cs
new file mode 100644
index 0000000..c66c8b3
--- /dev/null
+++ b/DMS.WPF/Services/EmailFunctionalityTestService.cs
@@ -0,0 +1,89 @@
+using DMS.Application.DTOs;
+using DMS.Application.Interfaces;
+using DMS.Core.Interfaces.Repositories;
+using DMS.Core.Interfaces.Services;
+using DMS.Core.Models;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace DMS.WPF.Services
+{
+ ///
+ /// 邮件功能测试服务
+ ///
+ public class EmailFunctionalityTestService
+ {
+ private readonly IEmailAppService _emailAppService;
+ private readonly IEmailAccountRepository _emailAccountRepository;
+ private readonly IEmailService _emailService;
+
+ public EmailFunctionalityTestService(
+ IEmailAppService emailAppService,
+ IEmailAccountRepository emailAccountRepository,
+ IEmailService emailService)
+ {
+ _emailAppService = emailAppService;
+ _emailAccountRepository = emailAccountRepository;
+ _emailService = emailService;
+ }
+
+ ///
+ /// 运行邮件功能测试
+ ///
+ public async Task RunTestAsync()
+ {
+ try
+ {
+ // 1. 创建测试邮件账户
+ var createRequest = new CreateEmailAccountRequest
+ {
+ Name = "测试邮件账户",
+ EmailAddress = "test@example.com",
+ SmtpServer = "smtp.example.com",
+ SmtpPort = 587,
+ EnableSsl = true,
+ Username = "test@example.com",
+ Password = "password",
+ ImapServer = "imap.example.com",
+ ImapPort = 993,
+ IsDefault = true,
+ IsActive = true
+ };
+
+ var createdAccount = await _emailAppService.CreateEmailAccountAsync(createRequest);
+ Console.WriteLine($"创建邮件账户成功,ID: {createdAccount.Id}");
+
+ // 2. 获取所有邮件账户
+ var accounts = await _emailAppService.GetAllEmailAccountsAsync();
+ Console.WriteLine($"获取到 {accounts.Count} 个邮件账户");
+
+ // 3. 测试连接(这会失败,因为我们使用的是假的服务器地址)
+ var connectionResult = await _emailAppService.TestEmailAccountAsync(createdAccount.Id);
+ Console.WriteLine($"邮件账户连接测试结果: {connectionResult}");
+
+ // 4. 创建测试邮件模板
+ var templateDto = new EmailTemplateDto
+ {
+ Name = "测试模板",
+ Code = "TEST_TEMPLATE",
+ Subject = "测试邮件主题",
+ Body = "测试邮件内容
这是一封测试邮件。
",
+ IsHtml = true,
+ IsActive = true
+ };
+
+ var createdTemplate = await _emailAppService.CreateEmailTemplateAsync(templateDto);
+ Console.WriteLine($"创建邮件模板成功,ID: {createdTemplate.Id}");
+
+ // 5. 获取所有邮件模板
+ var templates = await _emailAppService.GetAllEmailTemplatesAsync();
+ Console.WriteLine($"获取到 {templates.Count} 个邮件模板");
+
+ Console.WriteLine("邮件功能测试完成!");
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"邮件功能测试过程中发生错误: {ex.Message}");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/DMS.WPF/Services/NavigationService.cs b/DMS.WPF/Services/NavigationService.cs
index b616519..ef8ea54 100644
--- a/DMS.WPF/Services/NavigationService.cs
+++ b/DMS.WPF/Services/NavigationService.cs
@@ -94,6 +94,8 @@ public class NavigationService : INavigationService
return App.Current.Services.GetRequiredService();
case "SettingView":
return App.Current.Services.GetRequiredService();
+ case "EmailManagementView":
+ return App.Current.Services.GetRequiredService();
default:
return null;
}
diff --git a/DMS.WPF/ViewModels/Dialogs/EmailAccountDialogViewModel.cs b/DMS.WPF/ViewModels/Dialogs/EmailAccountDialogViewModel.cs
new file mode 100644
index 0000000..5c3888e
--- /dev/null
+++ b/DMS.WPF/ViewModels/Dialogs/EmailAccountDialogViewModel.cs
@@ -0,0 +1,161 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using DMS.Application.DTOs;
+using DMS.Application.Interfaces;
+using DMS.WPF.Interfaces;
+
+namespace DMS.WPF.ViewModels.Dialogs
+{
+ ///
+ /// 邮件账户对话框视图模型
+ ///
+ public partial class EmailAccountDialogViewModel : DialogViewModelBase, IDialogViewModel
+ {
+ private readonly IEmailAppService _emailAppService;
+ private readonly INotificationService _notificationService;
+ private bool _isEditMode;
+ private int _accountId;
+
+ [ObservableProperty]
+ private string _name = string.Empty;
+
+ [ObservableProperty]
+ private string _emailAddress = string.Empty;
+
+ [ObservableProperty]
+ private string _smtpServer = string.Empty;
+
+ [ObservableProperty]
+ private int _smtpPort = 587;
+
+ [ObservableProperty]
+ private bool _enableSsl = true;
+
+ [ObservableProperty]
+ private string _username = string.Empty;
+
+ [ObservableProperty]
+ private string _password = string.Empty;
+
+ [ObservableProperty]
+ private string _imapServer = string.Empty;
+
+ [ObservableProperty]
+ private int _imapPort = 993;
+
+ [ObservableProperty]
+ private bool _isDefault;
+
+ [ObservableProperty]
+ private bool _isActive = true;
+
+ [ObservableProperty]
+ private string _dialogTitle = "添加邮件账户";
+
+ public event Action? CloseRequested;
+
+ public EmailAccountDialogViewModel(
+ IEmailAppService emailAppService,
+ INotificationService notificationService)
+ {
+ _emailAppService = emailAppService;
+ _notificationService = notificationService;
+ PrimaryButText = "保存";
+ }
+
+ ///