記一次部署在docker環境專案傳送郵件出現No appropriate protocol

linyb極客之路發表於2023-01-10

前言

部門有個專案涉及到郵件傳送,傳送功能在本地測試可以成功傳送,但是打包部署到docker環境中,卻出現

No appropriate protocol (protocol is disabled or cipher suites are inappropriate)

後面在網上搜尋了一下,查到了這篇文章

https://stackoverflow.com/questions/67742776/docker-container-error-javax-mail-messagingexception-no-appropriate-protocol

這篇文章有個答主提到,他使用的版本的jdk 8u292,這個版本已經禁用了不安全的TLSv1&TLSv1.1,於是我就查了一下我們部署的docker基礎映象jdk版本,為jdk8u332。後面再搜尋了一下解決方案,大部分的解決方案都是透過修改java.security檔案中的jdk.tls.disabledAlgorithms配置,刪除掉TLSv1&TLSv1.1來解決

但是這種方案給我的感覺,有那麼點欠妥。畢竟jdk禁用TLSv1&TLSv1.1應該是經過考量的。所以一開始我就先把這個方案作為其他方案都無法解決的時候,最終兜底方案。下面就來回顧 一下,我的解決歷程

解決歷程

方案一:將mail.smtp.ssl.protocols配置為TLSv1.2

但改完後,報瞭如下異常

The server selected protocol version TLS10 is not accepted by client preferences [TLS12]

因為server端支援的TLSv1.0,因此沒招,mail.smtp.ssl.protocols就不能改為TLSv1.2

方案二:將javax.mail的包換成com.sun.mail
        <dependency>
            <groupId>com.sun.mail</groupId>
            <artifactId>javax.mail</artifactId>
            <version>1.6.2</version>
        </dependency>

該方案是來源如下博文
https://blog.csdn.net/qq_33601179/article/details/123069499
他透過調整mail的gav解決,但我經過實驗,發現該方案並沒解決我的問題,仍然會報

No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
方案三:進入docker容器內部,修改java.security檔案中的jdk.tls.disabledAlgorithms配置,刪除掉TLSv1&TLSv1.1

網上查了資料,大多數都是透過宿主機去修改java.security,透過docker去修改,基本上沒看到。

不過我們可以透過進入容器docker內部,進行修改。但要修改java.security,首先就得知道java.security檔案的位置。不同的基礎映象,java.security檔案的位置可能是不一樣的。

那如何知道java.security的具體位置呢? 這邊提供一個思路,如果是自制的基礎映象,可以去問公司自制這個映象的作者,如果是公有的映象,可以透過docker hub,比如我們這個專案的映象是用到skywalking-java-agent:8.11.0-java8,因此我們就可以去docker hub,搜尋該映象,然後點開詳情,裡面有的會有IMAGE LAYERS

由這個就可以知道java的基本路徑,然後進入容器內部


我們就可以透過vim命令去修改java.security檔案內容,不過正常修改的時候,要裝下vim

apt-get update
apt-get install vim

修改完重啟一下容器,然後透過訪問 ip:埠/actuator/health,前提要引入actuator

   <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

並配置

 endpoint:
      health:
        show-details: always

檢視mail的健康狀態

或者可以直接傳送測試郵件,驗證也可以

方案四:調整Dockerfile

其實方案四的實現邏輯和方案三是一樣的,核心也是修改java.security檔案中的jdk.tls.disabledAlgorithms配置,刪除掉TLSv1&TLSv1.1。但方案三有個弊端是,每次發版後,都要重新進入docker容器內部修改。方案四的方案是
在Dcokerfile檔案裡面新增如下內容

RUN sed -i 's/jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1/jdk.tls.disabledAlgorithms=SSLv3/g' /opt/java/openjdk/lib/security/java.security

本質就是在構建業務映象時,同時修改java.security內容,最終達到和方案三一樣的效果

方案五:降低jdk版本

這種方案雖然也可以達到效果,但是不建議就是,畢竟換了jdk,可能會導致其他不可預知的問題

總結

這幾種方案,因為1,2方案達不到目的,所以只能在3,4,5這三種方案選,基本上大多數都會選擇方案四。不過雖然是解決問題,但是始終感覺不是最佳方案,最佳方案可能是不改jdk內容,透過其他方式改,但暫時又沒其他思路,如果有更好的方案,大家可以留言告知

相關文章