1. ホーム
  2. java

java Mail send email smtp is not authenticated by TLS encryption solution.

2022-02-11 02:36:26

テストを開始する前に、メールを送信するサーバーで smtp サービスが利用可能であることを確認してください。

そうでない場合は、例外が発生します。

 Sending the email to the following server failed : m.xxx.com:25
Caused by: javax.mail.AuthenticationFailedException: 334 NTLM supported




現在使用している開発フレームワークはplayframeworkで、apacheのメールツールクラスをカプセル化するのに役立ち、以下のようなコードになります。

 public static void sendMail(SendMailDto sendMailDto){
        if(sendMailDto!=null){
            HtmlEmail email = new HtmlEmail();
            email.setCharset("UTF-8");// encoding format
            try {
                email.addTo(sendMailDto.accepterEmail);// recipient
                email.setFrom(sendMailDto.sender, sendMailDto.name);// sender, name
                email.setSubject(sendMailDto.title);// title of the email
                email.setMsg(sendMailDto.content);// send content
                Mail.send(email);
                Logger.info("Received email: "+sendMailDto.accepterEmail+" Sent successfully! ");
                Logger.info("Sending email server: "+sendMailDto.sender);
                Logger.info("Sending mail name: "+sendMailDto.name);

            }catch (Exception e) {
                Logger.info("Email: "+sendMailDto.accepterEmail+" Failed to send! ");
                e.printStackTrace();
            }
        }
    }



設定ファイルでアサートするため。

mail.smtp.host=xxxx
mail.smtp.user=xxxx
mail.smtp.pass=xxxx




基本的には、apacheのsetMailSession()メソッドがそのまま使用されます。

すべて設定し、実行を開始したところ、やはり上記の例外が報告され、設定ファイルにmail.smtp.protocol=smtpsを追加する必要があることがわかり、ソースコードを解析したところ、以下のようなことが判明しました。

 public static Session getSession() {
        if (session == null) {
            Properties props = new Properties();
            // Put a bogus value even if we are on dev mode, otherwise JavaMail will complain
            props.put("mail.smtp.host", Play.configuration.getProperty("mail.smtp.host", "localhost"));

            String channelEncryption;
            if (Play.configuration.containsKey("mail.smtp.protocol") && Play.configuration.getProperty("mail.smtp.protocol ", "smtp").equals("smtps")) {
                // Backward compatibility before stable5
                channelEncryption = "starttls";
            } else {
                channelEncryption = Play.configuration.getProperty("mail.smtp.channel", "clear");
            }

            if (channelEncryption.equals("clear")) {
                props.put("mail.smtp.port", "25");
            } else if (channelEncryption.equals("ssl")) {
                // port 465 + setup yes ssl socket factory (won't verify that the server certificate is signed with a root ca.)
                props.put("mail.smtp.port", "465");
                props.put("mail.smtp.socketFactory.port", "465");
                props.put("mail.smtp.socketFactory.class", "play.utils.YesSSLSocketFactory");
                props.put("mail.smtp.socketFactory.fallback", "false");
            } else if (channelEncryption.equals("starttls")) {
                // port 25 + enable starttls + ssl socket factory
                props.put("mail.smtp.port", "25");
                props.put("mail.smtp.starttls.enable", "true");
                // can't install our socket factory. will work only with server that has a signed certificate
                // story to be continued in javamail 1.4.2 : https://glassfish.dev.java.net/issues/show_bug.cgi?id=5189
            }

            if (Play.configuration.containsKey("mail.smtp.localhost")) {
                props.put("mail.smtp.localhost", Play.configuration.get("mail.smtp.localhost")); //override defaults
            }
            if (Play.configuration.containsKey("mail.smtp.socketFactory.class")) {
                props.put("mail.smtp.socketFactory.class", Play.configuration.get("mail.smtp.socketFactory.class"));
            }
            if (Play.configuration.containsKey("mail.smtp.port")) {
                props.put("mail.smtp.port", Play.configuration.get("mail.smtp.port"));
            }
            String user = Play.configuration.getProperty("mail.smtp.user");
            String password = Play.configuration.getProperty("mail.smtp.pass");
            if (password == null) {
                // Fallback to old convention
                password = Play.configuration.getProperty("mail.smtp.password");
            }
            String authenticator = Play.configuration.getProperty("mail.smtp.authenticator");
            session = null;

            if (authenticator ! = null) {
                props.put("mail.smtp.auth", "true");
                try {
                    session = Session.getInstance(props, (Authenticator) Play.c



後方互換性のために、セッションで設定する必要があります。

props.put("mail.smtp.port", "25");
props.put("mail.smtp.starttls.enable", "true");



設定後、もう一度試してみると、やはり例外が投げられていることがわかります。

javax.mail.MessagingException: Could not convert socket to TLS 
ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target



ソケットをTLSに解決できない(上のスクリーンショットからわかるように、私のメールサーバーはTLSで暗号化されている)。

アクセス先に有効な証明書を提供できない。

この点については、2つの解決策があります。

1. オンラインでセキュリティ証明書を生成する方法を見つけ、必要に応じて指定された場所に配置する:。 http://www.oschina.net/question/12_19249

2. 現在のsmtpホストを信頼できるように設定する props.put ("mail.smtp.ssl.trust", "smtp サーバーアドレス")

この時点で、すべての問題が解決されました。



要約すると

1つ目の例外の理由は3つあります。

1. メールサーバーのsmtpがオンになっていない。

2. ユーザー名・パスワードが間違っている。

3.メールツールクラスのバージョンが低く、ソケットファクトリが効率的に生成されない。


解決策:メールボックスにログインし、設定内のsmtpサービスをオンにし、ログインメールボックスのユーザー名とパスワードがプログラム内で正しく記入されていることを確認し、高いバージョンのmail.jarを使用するか、セッションでprops.put("mail.smtp.port", "25"); props. put("mail.smtp.starttls.enable", "true");


2つ目の例外が発生する原因

smtpが暗号化設定されているか、信頼できないアドレスにアクセスしようとした


解決方法 セキュリティ証明書をツールクラスで生成する(under \jdk1.6.0_31jjrelibsecurity)


apache mailについてはまだまだ分からないことが多いので、上記はあくまで問題を解決し、皆さんと一緒に勉強していく過程の記録です。