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

SMTP邮件发送失败:TLS套接字转换及PKIX证书路径错误

SMTP Email Sending Failed with SSLHandshakeException (PKIX Path Building Failed)

I'm trying to send emails via SMTP using port 578 (note: my Spring config shows port 587) and getting the following error:

Could not convert socket to TLS; nested exception is: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

Relevant Code & Configuration

EmailController.java

package com.jcg.spring.mvc.email;

import java.io.IOException;
import java.io.InputStream;
import javax.mail.internet.MimeMessage;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamSource;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.mail.javamail.MimeMessagePreparator;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class EmailController {
    static String emailToRecipient, emailSubject, emailMessage;
    static final String emailFromRecipient = "srinivasaraojella@gmail.com";
    static ModelAndView modelViewObj;

    @Autowired
    private JavaMailSender mailSenderObj;

    @RequestMapping(value = {"/", "emailForm"}, method = RequestMethod.GET)
    public ModelAndView showEmailForm(ModelMap model) {
        modelViewObj = new ModelAndView("emailForm");
        return modelViewObj;
    }

    // This Method Is Used To Prepare The Email Message And Send It To The Client
    @RequestMapping(value = "sendEmail", method = RequestMethod.POST)
    public ModelAndView sendEmailToClient(HttpServletRequest request, final @RequestParam CommonsMultipartFile attachFileObj) {
        // Reading Email Form Input Parameters
        emailSubject = request.getParameter("subject");
        emailMessage = request.getParameter("message");
        emailToRecipient = request.getParameter("mailTo");

        // Logging The Email Form Parameters For Debugging Purpose
        System.out.println("\nReceipient?= " + emailToRecipient + ", Subject?= " + emailSubject + ", Message?= " + emailMessage + "\n");

        mailSenderObj.send(new MimeMessagePreparator() {
            public void prepare(MimeMessage mimeMessage) throws Exception {
                MimeMessageHelper mimeMsgHelperObj = new MimeMessageHelper(mimeMessage, true, "UTF-8");
                mimeMsgHelperObj.setTo(emailToRecipient);
                mimeMsgHelperObj.setFrom(emailFromRecipient);
                mimeMsgHelperObj.setText(emailMessage);
                mimeMsgHelperObj.setSubject(emailSubject);

                // Determine If There Is An File Upload. If Yes, Attach It To The Client Email
                if ((attachFileObj != null) && (attachFileObj.getSize() > 0) && (!attachFileObj.equals(""))) {
                    System.out.println("\nAttachment Name?= " + attachFileObj.getOriginalFilename() + "\n");
                    mimeMsgHelperObj.addAttachment(attachFileObj.getOriginalFilename(), new InputStreamSource() {
                        public InputStream getInputStream() throws IOException {
                            return attachFileObj.getInputStream();
                        }
                    });
                } else {
                    System.out.println("\nNo Attachment Is Selected By The User. Sending Text Email!\n");
                }
            }
        });

        System.out.println("\nMessage Send Successfully.... Hurrey!\n");
        modelViewObj = new ModelAndView("success","messageObj","Thank You! Your Email Has Been Sent!");
        return modelViewObj;
    }
}

spring-servlet.xml (truncated)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <context:component-scan base-package="com.jcg.spring.mvc.email" />

    <!-- Spring Email Sender Bean Configuration -->
    <bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
        <property name="host" value="smtp.gmail.com" />
        <property name="port" value="587" />
        <property name="username" value="srinivasaraojella@gmail.com" />
        <property name="password" value="srinu877$@" />
        <property name="javaMailProperties">
            <props>
                <prop key="mail.smtp.auth">true</prop>
                <prop key="mail.debug">true</prop>
                <prop key="mail.transport.protocol">smtp</prop>
                <prop key="mail.smtp.socketFactory.class">javax.net.ssl.SSLSocketFactory</prop>
                <prop key="mail.smtp.socketFactory.port">465</prop>
                <prop key="mail.smtp.starttls.enable">true</prop>
            </props>
        </property>
    </bean>
</beans>

Solution

Let's fix this issue step by step. The error has two main root causes: conflicting SMTP configuration settings, and missing root certificates in Java's trust store.

1. Fix Conflicting SMTP Configuration

You're using port 587 (STARTTLS mode) for Gmail SMTP, but your config includes settings for 465 (SSL direct mode), which causes a conflict. Here's how to correct it:

Update the javaMailProperties section in your spring-servlet.xml to remove the socket factory settings (they're only for port 465):

<property name="javaMailProperties">
    <props>
        <prop key="mail.smtp.auth">true</prop>
        <prop key="mail.debug">true</prop>
        <prop key="mail.transport.protocol">smtp</prop>
        <prop key="mail.smtp.starttls.enable">true</prop>
        <!-- Optional: Force TLS connection (recommended) -->
        <prop key="mail.smtp.starttls.required">true</prop>
    </props>
</property>

Also, double-check the port: you mentioned using 578, but Gmail's standard SMTP ports are 587 (STARTTLS) and 465 (SSL). Use 587 unless your email provider specifies otherwise.

2. Resolve PKIX Certificate Trust Issue

The PKIX path building failed error means Java can't verify Gmail's SSL certificate because it doesn't have the necessary root certificate in its default trust store (cacerts). Here are three solutions, ordered by security:

Option 1: Import Gmail's Root Certificate (Production-Grade)

This is the safest method for production environments:

  1. Get Gmail's SMTP certificate:
    Run this OpenSSL command to fetch the certificate:

    openssl s_client -connect smtp.gmail.com:587 -starttls smtp
    

    Copy everything from -----BEGIN CERTIFICATE----- to -----END CERTIFICATE----- and save it as gmail.crt.

  2. Import the certificate into Java's trust store:
    Locate your Java cacerts file (usually in JAVA_HOME/jre/lib/security/cacerts for JDK 8, or JAVA_HOME/lib/security/cacerts for JDK 9+). Run this keytool command (default password is changeit):

    keytool -import -alias gmail-smtp -keystore /path/to/cacerts -file gmail.crt
    

    Confirm the import when prompted.

Option 2: Bypass Certificate Validation (Only for Development)

Never use this in production—it disables SSL security. But it's useful for quick testing:
Replace your mailSender bean with a custom implementation that skips certificate checks:

@Bean
public JavaMailSender mailSender() {
    JavaMailSenderImpl sender = new JavaMailSenderImpl();
    sender.setHost("smtp.gmail.com");
    sender.setPort(587);
    sender.setUsername("srinivasaraojella@gmail.com");
    // If you have 2FA enabled on Gmail, use an App Password instead of your regular password
    sender.setPassword("srinu877$@");

    Properties props = sender.getJavaMailProperties();
    props.put("mail.smtp.auth", "true");
    props.put("mail.smtp.starttls.enable", "true");
    props.put("mail.debug", "true");

    // Bypass SSL certificate validation
    try {
        TrustManager[] trustAllCerts = new TrustManager[]{
            new X509TrustManager() {
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
                public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {}
                public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {}
            }
        };
        SSLContext sc = SSLContext.getInstance("TLS");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        props.put("mail.smtp.ssl.socketFactory", sc.getSocketFactory());
    } catch (Exception e) {
        e.printStackTrace();
    }

    return sender;
}

Option 3: Update Java to the Latest Version

Older Java versions may not include the latest root certificates. Updating to the most recent JDK/JRE can automatically resolve the trust issue, as Oracle regularly updates the cacerts store.

3. Additional Gmail-Specific Fix

If you're still having trouble sending emails:

  • Enable App Passwords: If you have 2-Step Verification enabled on your Gmail account, you can't use your regular password. Generate an App Password (requires 2FA) and use that in your configuration.
  • Check Less Secure Apps: Google has phased out this option, but if you don't have 2FA enabled, you might need to enable "Less secure app access" (not recommended for long-term use).

内容的提问来源于stack exchange,提问作者Jalla Srinivasaraojella

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:52:55