You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot集成AWS SES与JavaMailSender遇AbstractMethodError求助

Spring Boot集成AWS SES时AbstractMethodError问题解决建议

问题场景

在Spring Boot应用中集成AWS SES,已添加相关依赖、编写邮件上下文抽象类及实现类,通过JavaMailSender创建MimeMessage发送邮件时,触发AbstractMethodError错误。

依赖配置

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-aws</artifactId>
    <version>2.1.0.RELEASE</version>
</dependency>
<dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>aws-java-sdk-ses</artifactId>
    <version>1.11.505</version>
</dependency>

<dependency>
    <groupId>javax.mail</groupId>
    <artifactId>javax.mail-api</artifactId>
    <version>1.6.2</version>
</dependency>

<dependency>
    <groupId>com.sun.mail</groupId>
    <artifactId>javax.mail</artifactId>
    <version>1.6.2</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
</dependency>

邮件上下文代码

public abstract class AbstractEmailContext {
    private String from;
    private String to;
    private String subject;
    private String email;
    private String attachment;
    private String fromDisplayName;
    private String emailLanguage;
    private String displayName;
    private String templateLocation;
    private Map<String, Object> context;
    // getter and setter methods

    public AbstractEmailContext() {
        this.context = new HashMap<>();
    }
    public abstract <T> void init(T context);

    public abstract <T> void rinit(T context);

    public Object put(String key, Object value) {
        return key == null ? null : this.context.put(key.intern(), value);
    }

    public String getTemplateLocation() {
        return templateLocation;
    }

    public void setTemplateLocation(String templateLocation) {
        this.templateLocation = templateLocation;
    }

    public void setContext(Map<String, Object> context) {
        this.context = context;
    }
}

public class AccountVerificationEmailContext extends AbstractEmailContext{

    private String token;

    @Override
    public <T> void init(T context){
        CCUser ccUser = (CCUser) context;
        put("name", ccUser.getName());
        setTemplateLocation("/confirm");
        setSubject("Complete your registration!");
        setFrom("no_reply@crosscheck.tech");
        setTo(ccUser.getEmail());
    }

    @Override
    public <T> void rinit(T context){
        CCUser ccUser = (CCUser) context;
        put("email", ccUser.getEmail());
        setTemplateLocation("/creset");
        setSubject("Change your Password!");
        setFrom("no_reply@crosscheck.tech");
        setTo(ccUser.getEmail());
    }

    public void setToken(String token){
        this.token = token;
        put("token", token);
    }

    public void buildVerificationUrl(final String baseUrl, final String token){
        final String url = UriComponentsBuilder.fromHttpUrl(baseUrl).path("/registration/verify").queryParam("token",token).toUriString();
        put("verificationURL",url);
    }

    public void buildResetUrl(final String baseUrl, final String token){
        final String url = UriComponentsBuilder.fromHttpUrl(baseUrl).path("/forgotpass/resetpass").queryParam("token",token).toUriString();
        put("verificationURL",url);
    }
}

邮件发送实现代码

@Autowired
private JavaMailSender emailSender;
@Autowired
private SpringTemplateEngine templateEngine;

@Override
public void sendMail(AbstractEmailContext email) throws MessagingException{

    MimeMessage message = emailSender.createMimeMessage();
    MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(message, MimeMessageHelper.MULTIPART_MODE_MIXED_RELATED, StandardCharsets.UTF_8.name());
    Context context = new Context();
    context.setVariables(email.getContext());
    String emailContent = templateEngine.process(email.getTemplateLocation(),context);

    mimeMessageHelper.setTo(email.getTo());
    mimeMessageHelper.setSubject(email.getSubject());
    mimeMessageHelper.setFrom(email.getFrom());
    mimeMessageHelper.setText(emailContent,true);
    emailSender.send(message);

}

报错栈

java.lang.AbstractMethodError: Receiver class org.springframework.cloud.aws.mail.simplemail.SimpleEmailServiceJavaMailSender does not define or inherit an implementation of the resolved method 'abstract jakarta.mail.internet.MimeMessage createMimeMessage()' of interface org.springframework.mail.javamail.JavaMailSender.
    at com.xr.crosscheck.service.CCEmailServiceImpl.sendMail(CCEmailServiceImpl.java:25) ~[classes/:na]
    at com.xr.crosscheck.service.UserServiceImpl.sendRegistrationConfirmationEmail(UserServiceImpl.java:104) ~[classes/:na]
    at com.xr.crosscheck.service.UserServiceImpl.register(UserServiceImpl.java:68) ~[classes/:na]
    at com.xr.crosscheck.controller.RegistrationController.userRegistration(RegistrationController.java:52) ~[classes/:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:262) ~[spring-web-6.1.2.jar:6.1.2]
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:190) ~[spring-web-6.1.2.jar:6.1.2]
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118) ~[spring-webmvc-6.1.2.jar:6.1.2]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:917) ~[spring-webmvc-6.1.2.jar:6.1.2]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:829) ~[spring-webmvc-6.1.2.jar:6.1.2]
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-6.1.2.jar:6.1.2]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089) ~[spring-webmvc-6.1.2.jar:6.1.2]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979) ~[spring-webmvc-6.1.2.jar:6.1.2]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) ~[spring-webmvc-6.1.2.jar:6.1.2]
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:914) ~[spring-webmvc-6.1.2.jar:6.1.2]

报错原因

核心是Jakarta EE与javax规范的依赖冲突:

  • 从报错栈中的spring-web-6.1.2可知,使用的是Spring Boot 3.x版本,该版本已全面切换到Jakarta EE规范,Spring Mail的JavaMailSender接口定义的createMimeMessage()方法返回的是jakarta.mail.internet.MimeMessage。
  • 引入的spring-cloud-starter-aws 2.1.0.RELEASE是基于旧版javax.mail的依赖,它提供的SimpleEmailServiceJavaMailSender实现的是javax版本的createMimeMessage()方法,与当前Spring Mail的接口签名不匹配,导致抽象方法未实现的错误。
  • 手动引入的javax.mail-api和com.sun.mail.javax.mail进一步加剧了依赖冲突,Spring Boot 3.x的spring-boot-starter-mail已经默认使用Jakarta Mail的依赖。

解决步骤

  1. 替换旧的AWS SES依赖
    移除spring-cloud-starter-aws和aws-java-sdk-ses,改用Spring Boot官方适配Jakarta EE的AWS邮件 starter:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aws-mail</artifactId>
        <!-- 版本由Spring Boot parent自动管理,无需手动指定 -->
    </dependency>
    

    或者直接使用AWS SDK v2的SES依赖(更推荐,支持最新AWS特性):

    <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>ses</artifactId>
    </dependency>
    
  2. 清理javax.mail相关依赖
    删除手动引入的javax.mail-api和com.sun.mail.javax.mail,因为spring-boot-starter-mail已经包含了Jakarta Mail的依赖:

    <!-- 移除这两个依赖 -->
    <dependency>
        <groupId>javax.mail</groupId>
        <artifactId>javax.mail-api</artifactId>
        <version>1.6.2</version>
    </dependency>
    <dependency>
        <groupId>com.sun.mail</groupId>
        <artifactId>javax.mail</artifactId>
        <version>1.6.2</version>
    </dependency>
    
  3. 配置AWS SES参数
    在application.properties或application.yml中配置AWS SES的SMTP信息:

    spring.mail.host=email-smtp.<你的AWS区域>.amazonaws.com
    spring.mail.username=你的SES SMTP用户名
    spring.mail.password=你的SES SMTP密码
    spring.mail.port=587
    spring.mail.properties.mail.smtp.auth=true
    spring.mail.properties.mail.smtp.starttls.enable=true
    
  4. 验证依赖树
    执行Maven命令检查是否还有javax.mail的残留依赖,如有则排除:

    mvn dependency:tree | grep javax.mail
    

注意事项

  • 如果选择使用AWS SDK v2直接调用SES API,需要调整邮件发送实现代码,改用SES客户端发送,而非JavaMailSender。
  • 确保你的AWS账号已正确配置SES权限,并且发送邮箱已通过验证。

内容的提问来源于stack exchange,提问作者SERKAN AYDOGDU

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 13:34:55