7月29日开始,腾讯修改了邮箱的加密方式,导致我们线上的所有的腾讯代收、代发邮件的功能全部失效。解决方法在最后,如果需要可直接跳转至解决方法一节

问题出现

7月29日开始,线上的所有的腾讯代收、代发邮件的功能全部失效,报handshake_error:

  1. javax.mail.MessagingException: Connect failed;
  2. nested exception is:
  3. javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
  4. at com.sun.mail.pop3.POP3Store.protocolConnect(POP3Store.java:209)
  5. at javax.mail.Service.connect(Service.java:295)
  6. at javax.mail.Service.connect(Service.java:176)
  7. at cn.irenshi.biz.recruit.service.impl.RecruitReceiveMailServiceImpl.testConnect(RecruitReceiveMailServiceImpl.java:507)
  8. at cn.irenshi.biz.recruit.service.impl.RecruitReceiveMailServiceImpl.testMailConnect(RecruitReceiveMailServiceImpl.java:534)
  9. at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  10. at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  11. at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  12. at java.lang.reflect.Method.invoke(Method.java:497)
  13. at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:302)
  14. at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
  15. at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
  16. ... more
  17. Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
  18. at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
  19. at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
  20. at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2023)
  21. at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1125)
  22. at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
  23. at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
  24. at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
  25. at com.sun.mail.util.SocketFetcher.configureSSLSocket(SocketFetcher.java:549)
  26. at com.sun.mail.util.SocketFetcher.createSocket(SocketFetcher.java:354)
  27. at com.sun.mail.util.SocketFetcher.getSocket(SocketFetcher.java:237)
  28. at com.sun.mail.pop3.Protocol.<init>(Protocol.java:112)
  29. at com.sun.mail.pop3.POP3Store.getPort(POP3Store.java:260)
  30. at com.sun.mail.pop3.POP3Store.protocolConnect(POP3Store.java:205)
  31. ... 132 more

记得当时用客户端链接腾讯的企业邮箱时,报证书警告,警告原因是pop.exmail.qq.com这个域名使用了pop.qq.com这个证书,应该是为了省钱吧。但是当用QQ个人邮箱连接的时候,确实使用了正确的证书,那错误原因应该不同。

问题定位

把问题交给做邮箱连接的同事,结果同事很快告诉我,他在windows上运行代码完全没有任何问题,并且JDK都用了相同的版本:1.8.0_u60。难道这个错误和系统相关?
打开Thunderbird尝试连接腾讯邮箱,发现一切也正常。可以断定这个问题不是系统相关的,问题一定出在我们的代码中。网上搜了一些handshake_failure相关的原因如下(StackOverflow):

  • Incompatible cipher suites in use by the client and the server. This would require the client to use (or enable) a cipher suite that is supported by the server.
  • Incompatible versions of SSL in use (the server might accept only TLS v1, while the client is capable of only using SSL v3). Again, the client might have to ensure that it uses a compatible version of the SSL/TLS protocol.
  • Incomplete trust path for the server certificate; the server's certificate is probably not trusted by the client. This would usually result in a more verbose error, but it is quite possible. Usually the fix is to import the server's CA certificate into the client's trust store.
  • The cerificate is issued for a different domain. Again, this would have resulted in a more verbose message, but I'll state the fix here in case this is the cause. The resolution in this case would be get the server (it does not appear to be yours) to use the correct certificate.

问题来了,如果以上是问题所在的话,一定会有一些错误信息输出,但为什么在我的系统中没有任何输出?

想到telnet,因为一般测试邮箱连接都直接使用telnet明文测试一下。当然这个想法是不可行的,如下:

  1. fify@fify-PC:~$ telnet pop.qq.com 995
  2. Trying 163.177.72.198...
  3. Connected to pop.qq.com.
  4. Escape character is '^]'.

没有办法输入任何东西,原因也很简单,995端口使用了加密。(这里犯迷糊了,现在握手错误就是因为加密问题...)

换一个方式连接POP邮箱:

  1. openssl s_client -connect pop.qq.com:995

输出如下:

  1. CONNECTED(00000003)
  2. depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA
  3. verify return:1
  4. depth=1 C = US, O = GeoTrust Inc., CN = GeoTrust SSL CA - G3
  5. verify return:1
  6. depth=0 C = CN, ST = Guangdong, L = Shenzhen, O = Shenzhen Tencent Computer Systems Company Limited, OU = R&D, CN = pop.qq.com
  7. verify return:1
  8. ---
  9. Certificate chain
  10. 0 s:/C=CN/ST=Guangdong/L=Shenzhen/O=Shenzhen Tencent Computer Systems Company Limited/OU=R&D/CN=pop.qq.com
  11. i:/C=US/O=GeoTrust Inc./CN=GeoTrust SSL CA - G3
  12. 1 s:/C=US/O=GeoTrust Inc./CN=GeoTrust SSL CA - G3
  13. i:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
  14. ---
  15. Server certificate
  16. -----BEGIN CERTIFICATE-----
  17. MIIGbzCCBVegAwIBAgIQZlTnxqFc/rVo50RzuVnejDANBgkqhkiG9w0BAQsFADBE
  18. MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMU
  19. R2VvVHJ1c3QgU1NMIENBIC0gRzMwHhcNMTYwMTI3MDAwMDAwWhcNMTYxMDIzMjM1
  20. OTU5WjCBkzELMAkGA1UEBhMCQ04xEjAQBgNVBAgTCUd1YW5nZG9uZzERMA8GA1UE
  21. BxQIU2hlbnpoZW4xOjA4BgNVBAoUMVNoZW56aGVuIFRlbmNlbnQgQ29tcHV0ZXIg
  22. U3lzdGVtcyBDb21wYW55IExpbWl0ZWQxDDAKBgNVBAsUA1ImRDETMBEGA1UEAxQK
  23. cG9wLnFxLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALeSY7Vb
  24. 60Cvv7P2O+zhaZnqlz/KFs//DH4It3xmyMPFOPUFopzN1h8n3/4FPqGBtqEEuWBE
  25. /o7soZT30E8bw30Tl07VOcYm/fPKi1pyro3hNEdLi5Wlta9fKxDAvw0U3clSq39R
  26. qihYIDAA3QrDuqI54gULa5IZnqM16A9VBULPfIDaXbdgaAIJ5Ak92nC13YcdQYuv
  27. egL6jOWSKzCRTqeRAg+6dWkfce1+gAOCuCUDgAso2EJ+k9nFe/LAMMGdGbe4KI9H
  28. CwpDCMo+2k2u4SQtXOmuYke7nNmRnpJeL3qZnGWsqT7l3N0mYCc/+3zcMfAcmyuo
  29. H90stoWF/G2T2rcCAwEAAaOCAwswggMHMIIBggYDVR0RBIIBeTCCAXWCCm14Mi5x
  30. cS5jb22CEmltYXAuZXhtYWlsLnFxLmNvbYISdXBsb2FkLm1haWwucXEuY29tgg90
  31. ZWwubWFpbC5xcS5jb22CFGh3c210cC5leG1haWwucXEuY29tgg9tb2IubWFpbC5x
  32. cS5jb22CEXJ0eC5leG1haWwucXEuY29tgg1teGJpejIucXEuY29tgg1teGJpejEu
  33. cXEuY29tgg5oay5tYWlsLnFxLmNvbYIOY2xvdWRteC5xcS5jb22CFGh3aW1hcC5l
  34. eG1haWwucXEuY29tggpteDEucXEuY29tghJzbXRwLmV4bWFpbC5xcS5jb22CEXBv
  35. cC5leG1haWwucXEuY29tghNod3BvcC5leG1haWwucXEuY29tggpteDMucXEuY29t
  36. ggtzbXRwLnFxLmNvbYIKZGF2LnFxLmNvbYIJZXgucXEuY29tgg9jbmMubWFpbC5x
  37. cS5jb22CC2ltYXAucXEuY29tggpwb3AucXEuY29tMAkGA1UdEwQCMAAwDgYDVR0P
  38. AQH/BAQDAgWgMCsGA1UdHwQkMCIwIKAeoByGGmh0dHA6Ly9nbi5zeW1jYi5jb20v
  39. Z24uY3JsMIGdBgNVHSAEgZUwgZIwgY8GBmeBDAECAjCBhDA/BggrBgEFBQcCARYz
  40. aHR0cHM6Ly93d3cuZ2VvdHJ1c3QuY29tL3Jlc291cmNlcy9yZXBvc2l0b3J5L2xl
  41. Z2FsMEEGCCsGAQUFBwICMDUMM2h0dHBzOi8vd3d3Lmdlb3RydXN0LmNvbS9yZXNv
  42. dXJjZXMvcmVwb3NpdG9yeS9sZWdhbDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYB
  43. BQUHAwIwHwYDVR0jBBgwFoAU0m/3lvSFP3I8MH0j2oV4m6N8WnwwVwYIKwYBBQUH
  44. AQEESzBJMB8GCCsGAQUFBzABhhNodHRwOi8vZ24uc3ltY2QuY29tMCYGCCsGAQUF
  45. BzAChhpodHRwOi8vZ24uc3ltY2IuY29tL2duLmNydDANBgkqhkiG9w0BAQsFAAOC
  46. AQEAvta4aGvK5qe31ZnLbmtblhgLD11dAdSom3sEnkF8UHtoi+gPiHBmHy1t39Du
  47. 2w+5aeriqwsetdDNuAhh6ckKJhGjc9ochWw2lvyuHPko8sSDdBd/oUYBh60lREwB
  48. DoAi7x37QIjia4yprFCNs/+bV+bee+2nijeNYibgwLQ+5jZL89jC6BVXxLSTenVw
  49. B2bzQPauNo+DOsB6ubY/i5r9p2E1DHAO9AluN/epJZ1gwZhYlOey71s59341w/ql
  50. ZJImDrWch+Gj1ZgnXWnttgOSafqynPA6VtiFyYGF4zLboxIkNiyuwj+ZzuugV97z
  51. IurYVE9FA7vTlfeJhAkG2gIwsA==
  52. -----END CERTIFICATE-----
  53. subject=/C=CN/ST=Guangdong/L=Shenzhen/O=Shenzhen Tencent Computer Systems Company Limited/OU=R&D/CN=pop.qq.com
  54. issuer=/C=US/O=GeoTrust Inc./CN=GeoTrust SSL CA - G3
  55. ---
  56. No client certificate CA names sent
  57. ---
  58. SSL handshake has read 3070 bytes and written 619 bytes
  59. ---
  60. New, TLSv1/SSLv3, Cipher is RC4-SHA
  61. Server public key is 2048 bit
  62. Secure Renegotiation IS supported
  63. Compression: NONE
  64. Expansion: NONE
  65. No ALPN negotiated
  66. SSL-Session:
  67. Protocol : TLSv1.2
  68. Cipher : RC4-SHA
  69. Session-ID: E278833690D2364F44B8E2B6D3F3708888411AD55298F02A0710C73FE229BBE9
  70. Session-ID-ctx:
  71. Master-Key: AF8A9394C87F52872A31DCC5ED62FF5F97B6F621CC9337E151D5F6229E9F231626F10B392A1938669EE72911ABD860D6
  72. Key-Arg : None
  73. PSK identity: None
  74. PSK identity hint: None
  75. SRP username: None
  76. TLS session ticket lifetime hint: 300 (seconds)
  77. TLS session ticket:
  78. 0000 - 6c 30 25 d9 92 71 25 7c-3e bd 7b e6 e2 a5 13 d1 l0%..q%|>.{.....
  79. 0010 - 9b f9 61 e6 3d dc e6 ea-96 9d 04 02 ea 6f 68 0f ..a.=........oh.
  80. 0020 - 18 a3 a3 e6 39 02 b9 d2-dd d1 2c 18 6d 9c 87 e5 ....9.....,.m...
  81. 0030 - 31 a9 53 a0 6c 2d 4c b6-d4 d6 35 ef d9 04 b0 b9 1.S.l-L...5.....
  82. 0040 - 70 af 82 74 1e 1d 26 9a-00 00 6b 90 2e eb 56 e9 p..t..&...k...V.
  83. 0050 - d8 f4 cd 56 d5 c2 02 80-0e d9 15 e5 2a b9 1f f3 ...V........*...
  84. 0060 - 8a 90 7b c0 72 6e c5 2a-04 2c 91 1c 11 fd 40 ba ..{.rn.*.,....@.
  85. 0070 - 38 fb db fb eb b7 65 e1-e1 51 1a e3 b2 f3 64 4e 8.....e..Q....dN
  86. 0080 - 54 6b 5f 0e 9d be 40 60-dd 68 8f 52 5d f3 48 36 Tk_...@`.h.R].H6
  87. 0090 - 40 7b 11 68 10 7f 7d e2-d6 93 19 48 42 f0 da bc @{.h..}....HB...
  88. Start Time: 1470455760
  89. Timeout : 300 (sec)
  90. Verify return code: 0 (ok)
  91. ---
  92. +OK QQMail POP3 Server v1.0 Service Ready(QQMail v2.0)

注意到以下片段

SSL-Session:
Protocol : TLSv1.2
Cipher : RC4-SHA

可以看到,加密使用的协议是TLSv1.2,Cipher使用的是RC4-SHA

那么问题是出在这两个地方吗?

JavaMail握手时的Protocol和Cipher

在Java启动中增加参数-Djavax.net.debug=all可以开启加密协议的调试模式。详情可以参考Oracle提供的文档

开启之后,连接邮箱握手的过程中打出了以下日志:

  1. trigger seeding of SecureRandom
  2. done seeding SecureRandom
  3. Ignoring unavailable cipher suite: TLS_DHE_DSS_WITH_AES_256_GCM_SHA384
  4. Ignoring unavailable cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA
  5. Ignoring unavailable cipher suite: TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
  6. Ignoring unavailable cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
  7. Ignoring unavailable cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
  8. Ignoring unavailable cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256
  9. Ignoring unavailable cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA
  10. Ignoring unavailable cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
  11. Ignoring unavailable cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
  12. Ignoring unavailable cipher suite: TLS_RSA_WITH_AES_256_GCM_SHA384
  13. Ignoring unavailable cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
  14. Ignoring unavailable cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
  15. Ignoring unavailable cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
  16. Ignoring unavailable cipher suite: TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
  17. Ignoring unavailable cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
  18. Ignoring unavailable cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
  19. Ignoring unavailable cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
  20. Ignoring unavailable cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
  21. Ignoring unavailable cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA
  22. Ignoring unavailable cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
  23. Ignoring unavailable cipher suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
  24. Allow unsafe renegotiation: false
  25. Allow legacy hello messages: true
  26. Is initial handshake: true
  27. Is secure renegotiation: false
  28. Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 for TLSv1
  29. Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 for TLSv1
  30. Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_128_CBC_SHA256 for TLSv1
  31. Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 for TLSv1
  32. Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 for TLSv1
  33. Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 for TLSv1
  34. Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 for TLSv1
  35. Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 for TLSv1.1
  36. Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 for TLSv1.1
  37. Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_128_CBC_SHA256 for TLSv1.1
  38. Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 for TLSv1.1
  39. Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 for TLSv1.1
  40. Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 for TLSv1.1
  41. Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 for TLSv1.1
  42. %% No cached client session
  43. *** ClientHello, TLSv1.2
  44. RandomCookie: GMT: 1453331365 bytes = { 172, 246, 197, 31, 208, 63, 31, 30, 107, 70, 211, 242, 90, 243, 100, 108, 44, 192, 70, 4, 238, 84, 176, 59, 5, 75, 162, 127 }
  45. Session ID: {}
  46. Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
  47. Compression Methods: { 0 }
  48. Extension elliptic_curves, curve names: {secp256r1, sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1, sect283k1, sect283r1, secp384r1, sect409k1, sect409r1, secp521r1, sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, secp192k1, sect193r1, sect193r2, secp224k1, sect239k1, secp256k1}
  49. Extension ec_point_formats, formats: [uncompressed]
  50. Extension signature_algorithms, signature_algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA224withECDSA, SHA224withRSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA, MD5withRSA
  51. Extension server_name, server_name: [type=host_name (0), value=pop.qq.com]
  52. ***
  53. [write] MD5 and SHA1 hashes: len = 214
  54. 0000: 01 00 00 D2 03 03 57 A0 14 A5 AC F6 C5 1F D0 3F ......W........?
  55. 0010: 1F 1E 6B 46 D3 F2 5A F3 64 6C 2C C0 46 04 EE 54 ..kF..Z.dl,.F..T
  56. 0020: B0 3B 05 4B A2 7F 00 00 3A C0 23 C0 27 00 3C C0 .;.K....:.#.'.<.
  57. 0030: 25 C0 29 00 67 00 40 C0 09 C0 13 00 2F C0 04 C0 %.).g.@...../...
  58. 0040: 0E 00 33 00 32 C0 2B C0 2F 00 9C C0 2D C0 31 00 ..3.2.+./...-.1.
  59. 0050: 9E 00 A2 C0 08 C0 12 00 0A C0 03 C0 0D 00 16 00 ................
  60. 0060: 13 00 FF 01 00 00 6F 00 0A 00 34 00 32 00 17 00 ......o...4.2...
  61. 0070: 01 00 03 00 13 00 15 00 06 00 07 00 09 00 0A 00 ................
  62. 0080: 18 00 0B 00 0C 00 19 00 0D 00 0E 00 0F 00 10 00 ................
  63. 0090: 11 00 02 00 12 00 04 00 05 00 14 00 08 00 16 00 ................
  64. 00A0: 0B 00 02 01 00 00 0D 00 1A 00 18 06 03 06 01 05 ................
  65. 00B0: 03 05 01 04 03 04 01 03 03 03 01 02 03 02 01 02 ................
  66. 00C0: 02 01 01 00 00 00 0F 00 0D 00 00 0A 70 6F 70 2E ............pop.
  67. 00D0: 71 71 2E 63 6F 6D qq.com
  68. http-nio-8080-exec-2, WRITE: TLSv1.2 Handshake, length = 214
  69. [Raw write]: length = 219
  70. 0000: 16 03 03 00 D6 01 00 00 D2 03 03 57 A0 14 A5 AC ...........W....
  71. 0010: F6 C5 1F D0 3F 1F 1E 6B 46 D3 F2 5A F3 64 6C 2C ....?..kF..Z.dl,
  72. 0020: C0 46 04 EE 54 B0 3B 05 4B A2 7F 00 00 3A C0 23 .F..T.;.K....:.#
  73. 0030: C0 27 00 3C C0 25 C0 29 00 67 00 40 C0 09 C0 13 .'.<.%.).g.@....
  74. 0040: 00 2F C0 04 C0 0E 00 33 00 32 C0 2B C0 2F 00 9C ./.....3.2.+./..
  75. 0050: C0 2D C0 31 00 9E 00 A2 C0 08 C0 12 00 0A C0 03 .-.1............
  76. 0060: C0 0D 00 16 00 13 00 FF 01 00 00 6F 00 0A 00 34 ...........o...4
  77. 0070: 00 32 00 17 00 01 00 03 00 13 00 15 00 06 00 07 .2..............
  78. 0080: 00 09 00 0A 00 18 00 0B 00 0C 00 19 00 0D 00 0E ................
  79. 0090: 00 0F 00 10 00 11 00 02 00 12 00 04 00 05 00 14 ................
  80. 00A0: 00 08 00 16 00 0B 00 02 01 00 00 0D 00 1A 00 18 ................
  81. 00B0: 06 03 06 01 05 03 05 01 04 03 04 01 03 03 03 01 ................
  82. 00C0: 02 03 02 01 02 02 01 01 00 00 00 0F 00 0D 00 00 ................
  83. 00D0: 0A 70 6F 70 2E 71 71 2E 63 6F 6D .pop.qq.com
  84. javax.mail.MessagingException: Connect failed;
  85. nested exception is:
  86. javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
  87. at com.sun.mail.pop3.POP3Store.protocolConnect(POP3Store.java:209)
  88. at javax.mail.Service.connect(Service.java:295)
  89. at javax.mail.Service.connect(Service.java:176)
  90. at cn.irenshi.biz.recruit.service.impl.RecruitReceiveMailServiceImpl.testConnect(RecruitReceiveMailServiceImpl.java:507)
  91. at cn.irenshi.biz.recruit.service.impl.RecruitReceiveMailServiceImpl.testMailConnect(RecruitReceiveMailServiceImpl.java:534)
  92. at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  93. at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  94. at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  95. at java.lang.reflect.Method.invoke(Method.java:497)
  96. at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:302)
  97. at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
  98. at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
  99. at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
  100. at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281)
  101. at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
  102. at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
  103. at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
  104. at com.sun.proxy.$Proxy1083.testMailConnect(Unknown Source)
  105. at cn.irenshi.web.controller.recruit.RecruitReceiveMailController.testMailConnect(RecruitReceiveMailController.java:116)
  106. at cn.irenshi.web.controller.recruit.RecruitReceiveMailController$$FastClassBySpringCGLIB$$4d626811.invoke(<generated>)
  107. at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
  108. at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:717)
  109. at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
  110. at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:68)
  111. at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
  112. at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
  113. at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
  114. at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653)
  115. at ...
  116. Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
  117. at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
  118. at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
  119. at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2023)
  120. at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1125)
  121. at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
  122. at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
  123. at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
  124. at com.sun.mail.util.SocketFetcher.configureSSLSocket(SocketFetcher.java:549)
  125. at com.sun.mail.util.SocketFetcher.createSocket(SocketFetcher.java:354)
  126. at com.sun.mail.util.SocketFetcher.getSocket(SocketFetcher.java:237)
  127. at com.sun.mail.pop3.Protocol.<init>(Protocol.java:112)
  128. at com.sun.mail.pop3.POP3Store.getPort(POP3Store.java:260)
  129. at com.sun.mail.pop3.POP3Store.protocolConnect(POP3Store.java:205)
  130. ... 132 more
  131. [Raw read]: length = 5
  132. 0000: 15 03 03 00 02 .....
  133. [Raw read]: length = 2
  134. 0000: 02 28 .(
  135. http-nio-8080-exec-2, READ: TLSv1.2 Alert, length = 2
  136. http-nio-8080-exec-2, RECV TLSv1.2 ALERT: fatal, handshake_failure
  137. http-nio-8080-exec-2, called closeSocket()
  138. http-nio-8080-exec-2, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

注意到:

Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]

发现其中果然没有RC4相关的Cipher Suites。

在同事Windows机器上试了以下,输入果然不同,如下:

Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, SSL_RSA_WITH_RC4_128_SHA, TLS_ECDH_ECDSA_WITH_RC4_128_SHA, TLS_ECDH_RSA_WITH_RC4_128_SHA, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_RC4_128_MD5, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]

赫然发现:SSL_RSA_WITH_RC4_128_SHA。这正是我们想要的东西。

解决问题

问题找到了,解决办法应该也比较容易找到。查看POP协议相关的所有参数,找到了mail.pop3.ssl.ciphersuites。在JavaMail的Properties中增加相关的SSL_RSA_WITH_RC4_128_SHA

  1. prop.setProperties("mail.pop3s.ssl.ciphersuites", "SSL_RSA_WITH_RC4_128_SHA");

重启服务器,测试,一气呵成,结果:handshake_failure

还是系统问题?

SSL_RSA_WITH_RC4_128_SHA为关键字搜索,搜到了这篇文章:Java 8 update 60 disables "RC4" cipher suites: Causes issues with Blancco erasure software and MC 3 communication。这是别的软件遇到的问题,但原因是一样的。

原来从JDK 1.8.0_u60开始,默认禁止了RC4这个算法。可以在{JRE_HOME}/lib/security/java.security找到相关配置:

534 jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768

以及

586 jdk.tls.legacyAlgorithms= \
587 K_NULL, C_NULL, M_NULL, \
588 DHE_DSS_EXPORT, DHE_RSA_EXPORT, DH_anon_EXPORT, DH_DSS_EXPORT, \
589 DH_RSA_EXPORT, RSA_EXPORT, \
590 DH_anon, ECDH_anon, \
591 RC4_128, RC4_40, DES_CBC, DES40_CBC

那Windows中同样的JDK版本,为什么却可以正常使用呢?比较发现在Windows安装之后的Java目录中,有两个部分,一个是JDK目录(其中包含一个JRE目录),一个是直接的JRE目录。打开两个java.security文件,惊奇的发现两个文件并不相同,JRE目录中的java.security并不包含禁用RC4算法这些配置。

解决方法

启用Java的RC4算法

没有去深研究为什么JDK会默认禁止这个算法,也不知道腾讯为什么会重新选择了一个JDK默认禁用的算法(7月29日之前是没有问题的)。但由于需要用到QQ邮箱,所以必须得开启这个算法。开启步骤如下:

  1. Go to the Java JRE installation folder: {JRE_HOME}\lib\security\
  2. Locate java.security file.
  3. Make a backup copy of the file.
  4. Edit the java.security file with a text editor software (for example Notepad) according to the example further below.
  1. 534c534
  2. - jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768
  3. + jdk.tls.disabledAlgorithms=SSLv3, MD5withRSA, DH keySize < 768
  4. 591c591
  5. - RC4_128, RC4_40, DES_CBC, DES40_CBC
  6. + DES_CBC, DES40_CBC

启用协议

在POP/SMTP的协议中增加最新的TLSv1.2协议:

  1. prop.setProperties("mail.pop3s.ssl.protocols", "TSLv1 TSLv1.1 TLSv1.2");

  1. prop.setProperties("mail.smtps.ssl.protocols", "TSLv1 TSLv1.1 TLSv1.2");

启用Cipher Scites

因为我需要兼容的不只是RC4这个算法,所以我启用了大部分的Cipher Suites

  1. prop.setProperties("mail.pop3s.ssl.ciphersuites", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA TLS_RSA_WITH_AES_128_CBC_SHA TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA TLS_ECDH_RSA_WITH_AES_128_CBC_SHA TLS_DHE_RSA_WITH_AES_128_CBC_SHA TLS_DHE_DSS_WITH_AES_128_CBC_SHA TLS_ECDHE_ECDSA_WITH_RC4_128_SHA TLS_ECDHE_RSA_WITH_RC4_128_SHA SSL_RSA_WITH_RC4_128_SHA TLS_ECDH_ECDSA_WITH_RC4_128_SHA TLS_ECDH_RSA_WITH_RC4_128_SHA TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA SSL_RSA_WITH_3DES_EDE_CBC_SHA TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA SSL_RSA_WITH_RC4_128_MD5 TLS_EMPTY_RENEGOTIATION_INFO_SCSV");

  1. prop.setProperties("mail.smtps.ssl.ciphersuites", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA TLS_RSA_WITH_AES_128_CBC_SHA TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA TLS_ECDH_RSA_WITH_AES_128_CBC_SHA TLS_DHE_RSA_WITH_AES_128_CBC_SHA TLS_DHE_DSS_WITH_AES_128_CBC_SHA TLS_ECDHE_ECDSA_WITH_RC4_128_SHA TLS_ECDHE_RSA_WITH_RC4_128_SHA SSL_RSA_WITH_RC4_128_SHA TLS_ECDH_ECDSA_WITH_RC4_128_SHA TLS_ECDH_RSA_WITH_RC4_128_SHA TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA SSL_RSA_WITH_3DES_EDE_CBC_SHA TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA SSL_RSA_WITH_RC4_128_MD5 TLS_EMPTY_RENEGOTIATION_INFO_SCSV");

RC4被JDK8默认禁用导致腾讯QQ邮箱无法访问的更多相关文章

  1. 技术笔记:Indy IdSMTP支持腾讯QQ邮箱邮件发送

    1.腾讯QQ邮箱的授权码问题 因为腾讯邮箱折腾了个底朝天,其要搞什么授权码登录第三方客户端,否则会报这个错误: 'Error: 请使用授权码登录.详情请看: http://service.mail.q ...

  2. Python+ Selenium自动化登录腾讯QQ邮箱实例

    学习了Python语言一段时间后,在公司的项目里也使用到了python来写测试脚本,一些重复的操作都使用脚本来处理了.大大的提高工作效率,减少了一些手工重复的操作. 以下是使用unittest框架写的 ...

  3. (更新)Java + 腾讯企业邮箱 + javamail + SSL 发送邮件

    咳咳~最头疼的就是莫名其妙的错误. 本来今年6月份运行通过的代码,过俩月就报错了. javax.mail.MessagingException: Could not connect to SMTP h ...

  4. 2、阿里云ECS发送邮件到腾讯企业邮箱(ECS默认不开启25端口)

    阿里云ECS默认禁用25端口导致发邮件失败. 方法一: 使用shell脚本发送邮件,需要配置mailx 1.安装软件 yum install mailx 2.配置 vim /etc/mail.rc在文 ...

  5. docker配置仓储库时出错:无法安全地用该源进行更新,所以默认禁用该源

    在Ubuntu上安装docker,配置仓储库时第一次使用了阿里去的镜像,如下 sudo add-apt-repository "deb [arch=amd64] http://mirrors ...

  6. 解决Safari高版本浏览器中默认禁用第三方COOKIE(含demo)

    前段时间在项目里遇到了一个比较头疼的问题,就是高版本的Safari中默认会阻止第三方cookie,这使得使用Safari浏览器的用户无法按照正常的业务逻辑进行操作. 问题展现 知识点 什么是第三方co ...

  7. ipv6禁用导致rpcbind服务启动失败实例

    ipv6禁用导致rpcbind服务启动失败实例     昨天在做服务器磁盘分区扩容的时候出现过一个服务启动的问题,在此记录.情景再现:前天晚上申请做磁盘扩容,得到批准后,昨天早上5点开始做停机调整维护 ...

  8. zookeeper的maxSessionTimeout默认值导致hbase regionserver超时

    zookeeper的maxSessionTimeout默认值导致hbase regionserver超时 在hbase中经常会遇到regionserver挂掉的情况,查看日志会看到这样的错误信息 20 ...

  9. ubuntu : 无法安全地用该源进行更新,所以默认禁用该源。

    sudo apt update报错: 无法安全地用该源进行更新,所以默认禁用该源. 1.检查是否是网络出了问题,修改DNS:114.114.114.114,8.8.8.8 断开网卡再重新连接,成功! ...

随机推荐

  1. Python 内置函数2

    print(list("胡辣汤")) lst = ["河南话", "四川话", "东北", "山东" ...

  2. HDU 6050 17多校2 Funny Function(数学+乘法逆元)

    Problem Description Function Fx,ysatisfies:For given integers N and M,calculate Fm,1 modulo 1e9+7.   ...

  3. ecmall 基础类分析

    class ECBaseApp,继承自class BaseApp,是includes/ecapp.base.php文件. 该类是一个非常重要的类,他是各个APP的应用的基础继承类.处理相关的基础应用. ...

  4. 何时使用SUM()与SUMX()

    概述 SUM()是一个聚合函数.在应用将影响公式的所有过滤器后,它会将您指定的单个列中的所有值相加.SUM()不知道行的存在(它不能逐行求值) - 它所能做的就是在应用过滤器之后将所有内容添加到它所呈 ...

  5. Linux audit安全审计工具

    /********************************************************************** * Linux audit安全审计工具 * 说明: * ...

  6. Oracle导入导出表

    使用PL SQL Developer进行操作 一.导出 工具<<导出表<<sql插入<<选择用户和要导出的表,勾选创建表,选择输出文件(格式最好为.sql),点击导 ...

  7. 【java多线程】java8的流操作api和fork/join框架

    原文:https://blog.csdn.net/u011001723/article/details/52794455/ 一.测试一个案例,说明java8的流操作是并行操作 1.代码 package ...

  8. readv与writev

    [root@bogon mycode]# cat writev.c #include<stdio.h> #include<string.h> #include<unist ...

  9. Gravitee.io 架构

    Gravitee.io 官方文档提供了几张架构图,通过图我们可以有一个整体的认识. 全局架构 平台架构 参考资料 https://docs.gravitee.io/apim_overview_arch ...

  10. Quartz.NET-2.3.3 各种 数据库配置 类别大全

    <!--SqlServer <add key="quartz.dataSource.myDS.connectionString" value="Data So ...