Quarkus Mailer 动态多租户/多种配置

问题描述 投票:0回答:1

Quarkus Mailer 似乎是 Quarkus 的现代 JavaMail 替代品。如何将其用于多租户?

我知道它支持“静态”接线,例如https://quarkus.io/guides/mailer-reference#multiple-mailer-configurations

编辑:我正在构建一个 SaaS,我的客户可以使用我的平台向使用他们自己的品牌的他们的客户发送电子邮件。例如,假设我正在构建一个 Salesforce 克隆,X 公司的销售人员可以从我的应用程序发送电子邮件,但这些电子邮件是使用他们自己(X 公司)的邮件设置进行“品牌化”的,例如来自 [电子邮件受保护]。显然,我想将每个客户的电子邮件设置存储在数据库中,而不是每次有新客户时手动编辑

application.properties

java email quarkus
1个回答
0
投票

我刚刚浏览了文档 https://quarkus.io/guides/mailer-reference#multiple-mailer-configurations

我们需要考虑在哪里可以保存各种租户及其域名。

如果我们将租户信息保存在mail_settings表中,我们可以参考下面的骨架代码
创建tenant_mail_settings表

CREATE TABLE tenant_mail_settings (
    tenant_id INT PRIMARY KEY,
    mail_host VARCHAR(255),
    mail_port INT,
    mail_username VARCHAR(255),
    mail_password VARCHAR(255)
);

定义其实体和存储库

@Entity
public class TenantMailSettings {
    @Id
    private Long tenantId;
    private String mailHost;
    private int mailPort;
    private String mailUsername;
    private String mailPassword;

    // Getters and setters
}

@ApplicationScoped
public class TenantMailSettingsRepository implements PanacheRepository<TenantMailSettings> {
    public Optional<TenantMailSettings> findByTenantId(Long tenantId) {
        return find("tenantId", tenantId).firstResultOptional();
    }
}

租户服务

@ApplicationScoped
public class TenantService {
    @Inject
    TenantMailSettingsRepository repository;

    public TenantMailSettings getMailSettings(Long tenantId) {
        return repository.findByTenantId(tenantId)
                         .orElseThrow(() -> new IllegalArgumentException("No settings found for tenant: " + tenantId));
    }
}

@ApplicationScoped
public class DynamicMailerConfig {
    @Inject
    TenantIdentifier tenantIdentifier;
    @Inject
    TenantService tenantService;
    @Inject
    Mailer mailer;

    @PostConstruct
    public void configureMailer() {
        Long tenantId = tenantIdentifier.getCurrentTenantId();
        TenantMailSettings settings = tenantService.getMailSettings(tenantId);
        mailer = MailerBuilder.withSMTPServer(settings.getMailHost(), settings.getMailPort())
                              .withSMTPUsername(settings.getMailUsername())
                              .withSMTPPassword(settings.getMailPassword())
                              .build();
    }
}

@ApplicationScoped
public class MailSender {
    @Inject
    DynamicMailerConfig dynamicMailerConfig;

    public void sendEmail(String to, String subject, String body) {
        Mail mail = Mail.withText(to, subject, body);
        dynamicMailerConfig.mailer.send(mail);
    }
}

识别当前租户:实现识别当前租户的方法。这可能基于请求标头、令牌或任何其他特定于上下文的数据。在这里,我将其硬编码为 123L,以获得一个简单的解决方案

@ApplicationScoped
public class TenantIdentifier {
    public Long getCurrentTenantId() {
        // Logic to get the current tenant ID, e.g., from a request header
        return 123L;  // example tenant ID
    }
}

以下是我对如何获取tenantId的一些想法

  1. 请求头
public Long getCurrentTenantId() {
    String tenantIdStr = request.getHeader("X-Tenant-ID");
    if (tenantIdStr == null || tenantIdStr.isEmpty()) {
        throw new IllegalArgumentException("Tenant ID header is missing or empty");
    }
    return Long.parseLong(tenantIdStr);
}

  1. 通过注入 HttpServletRequest 从子域或路径
public Long getCurrentTenantId() {
   String serverName = request.getServerName();
   // Extract tenant ID from subdomain, e.g., tenant1.example.com -> tenant1
   String tenantIdStr = extractTenantIdFromSubdomain(serverName);
   return Long.parseLong(tenantIdStr);
}

private String extractTenantIdFromSubdomain(String serverName) {
   return serverName.split("\\.")[0];
}
  1. 通过注入 JsonWebToken 获得 JWT 令牌
public Long getCurrentTenantId() {
    String tenantIdStr = jwt.getClaim("tenant_id");
    if (tenantIdStr == null || tenantIdStr.isEmpty()) {
        throw new IllegalArgumentException("Tenant ID claim is missing or empty");
    }
    return Long.parseLong(tenantIdStr);
}

请告诉我我是否正确理解了您的问题以及框架代码是否符合您的要求。

© www.soinside.com 2019 - 2024. All rights reserved.