elunez/eladmin · error · BadRequestException

请先配置,再操作

Error message

请先配置,再操作

What it means

Thrown by EmailServiceImpl.send(emailVo, emailConfig) when emailConfig.getId() == null — the caller passed a transient EmailConfig, which per find() only happens when no row with id=1 exists in the email config table (find() returns new EmailConfig() via orElseGet). So the admin has never saved SMTP settings; sending is refused before any SMTP connection is attempted.

Source

Thrown at eladmin-tools/src/main/java/me/zhengjie/service/impl/EmailServiceImpl.java:68

        if(!emailConfig.getPass().equals(old.getPass())){
            // 对称加密
            emailConfig.setPass(EncryptUtils.desEncrypt(emailConfig.getPass()));
        }
        return emailRepository.save(emailConfig);
    }

    @Override
    @Cacheable(key = "'config'")
    public EmailConfig find() {
        Optional<EmailConfig> emailConfig = emailRepository.findById(1L);
        return emailConfig.orElseGet(EmailConfig::new);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void send(EmailVo emailVo, EmailConfig emailConfig){
        if(emailConfig.getId() == null){
            throw new BadRequestException("请先配置,再操作");
        }
        // 封装
        MailAccount account = new MailAccount();
        // 设置用户
        String user = emailConfig.getFromUser().split("@")[0];
        account.setUser(user);
        account.setHost(emailConfig.getHost());
        account.setPort(Integer.parseInt(emailConfig.getPort()));
        account.setAuth(true);
        try {
            // 对称解密
            account.setPass(EncryptUtils.desDecrypt(emailConfig.getPass()));
        } catch (Exception e) {
            throw new BadRequestException(e.getMessage());
        }
        account.setFrom(emailConfig.getUser()+"<"+emailConfig.getFromUser()+">");
        // ssl方式发送
        account.setSslEnable(true);

View on GitHub (pinned to 55fbf70595)

Solutions

  1. Open the tools -> email config admin page and save host, port, fromUser, password (id becomes 1L).
  2. Verify row id=1 exists in email_config and that find() now returns it (clear the 'config' cache key if a stale empty object was cached).
  3. Ensure the config save path uses @CachePut(key='config') (mirroring AliPayServiceImpl) so the empty cached entry is replaced on save.
  4. Sequence smoke tests: configure email before any test that sends mail.

Example fix

// before
public void send(EmailVo emailVo, EmailConfig emailConfig){
    if(emailConfig.getId() == null){
        throw new BadRequestException("请先配置,再操作");
    }

// after (caller-side, in the verify-code flow):
EmailConfig config = emailService.find();
if(config.getId() == null){
    throw new BadRequestException("邮箱服务未配置,请联系管理员先完成邮箱设置");
}
emailService.send(emailService.sendEmail(email, key), config);
Defensive patterns

Strategy: validation

Validate before calling

// before any send flow
EmailConfig config = emailService.find();
if (config.getId() == null) {
    throw new BadRequestException("邮箱未配置,请先在后台保存邮箱设置");
}
emailService.send(emailVo, config);

Try / catch

try { emailService.send(emailVo, config); } catch (BadRequestException e) { if ("请先配置,再操作".equals(e.getMessage())) { /* route to email config page; this is setup, not transient */ } }

Prevention

When it happens

Trigger: Triggering any flow that sends mail (e.g. the verification-code endpoint that calls verifyCode then emailService.send) on a system where the tools email config was never saved; find() is @Cacheable so an empty EmailConfig can also get cached under 'config' after a failed first lookup.

Common situations: Fresh deployment without the email config row; DB migration that dropped email_config; the cached empty config not invalidated after saving real config if save() doesn't @CachePut the same key; testing the 'send code' button before completing setup.

Related errors


AI-assisted analysis of elunez/eladmin@55fbf70595 (2026-08-14). Data as JSON: /api/errors/7e56d30b34304a48. Report an issue: GitHub.