From 2b97284396dc3eae4f9db7bb8f0716836a854e3f Mon Sep 17 00:00:00 2001 From: Loong Wan Date: Sat, 31 Oct 2026 21:45:35 +0800 Subject: [PATCH 01/20] ci: use Maven 4 wrapper for feature/3.0.x --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7a03907..85e055c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,7 +4,7 @@ # - push / pull_request on the feature/3.0.x branch # - manual workflow_dispatch # -# Runs `mvn -B clean verify` which includes the JaCoCo coverage gate +# Runs `sh ./mvnw -B clean verify` which includes the JaCoCo coverage gate # (90% line coverage, haltOnFailure=false) configured in the POM. name: CI @@ -35,7 +35,7 @@ jobs: cache: maven - name: Build and verify with JaCoCo coverage gate - run: mvn -B --no-transfer-progress clean verify + run: sh ./mvnw -B --no-transfer-progress clean verify - name: Upload JaCoCo coverage report if: always() From dc3dcdeda2d5192cb6e731d54db4c621565bb2a0 Mon Sep 17 00:00:00 2001 From: Loong Wan Date: Sat, 31 Oct 2026 22:00:35 +0800 Subject: [PATCH 02/20] fix: handle missing network interface and indexed bean arrays --- .../java/hitool/core/lang3/network/MacAddressUtils.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hitool-core/src/main/java/hitool/core/lang3/network/MacAddressUtils.java b/hitool-core/src/main/java/hitool/core/lang3/network/MacAddressUtils.java index 427601e..ce1511a 100644 --- a/hitool-core/src/main/java/hitool/core/lang3/network/MacAddressUtils.java +++ b/hitool-core/src/main/java/hitool/core/lang3/network/MacAddressUtils.java @@ -273,7 +273,11 @@ public static String getHostMacAddress(String host) { // 获得网络接口对象(即网卡),并得到mac地址,mac地址存在于一个byte数组中。 byte[] mac = null; try { - mac = NetworkInterface.getByInetAddress(InetAddress.getByName(host)).getHardwareAddress(); + NetworkInterface networkInterface = NetworkInterface.getByInetAddress(InetAddress.getByName(host)); + if (networkInterface == null) { + return null; + } + mac = networkInterface.getHardwareAddress(); } catch (SocketException e) { e.printStackTrace(); } catch (UnknownHostException e) { From 7e85e977f03ff34888eeab194bad10d77bbe0d60 Mon Sep 17 00:00:00 2001 From: Loong Wan Date: Sat, 31 Oct 2026 22:00:38 +0800 Subject: [PATCH 03/20] fix: handle missing network interface and indexed bean arrays --- .../core/beanutils/BeanPropertyUtils.java | 47 +++++++------------ 1 file changed, 18 insertions(+), 29 deletions(-) diff --git a/hitool-core/src/main/java/hitool/core/beanutils/BeanPropertyUtils.java b/hitool-core/src/main/java/hitool/core/beanutils/BeanPropertyUtils.java index 28b39ee..e407c0f 100644 --- a/hitool-core/src/main/java/hitool/core/beanutils/BeanPropertyUtils.java +++ b/hitool-core/src/main/java/hitool/core/beanutils/BeanPropertyUtils.java @@ -244,36 +244,25 @@ public static void setProperty(Object bean, String name, Object value, String name3 = matcher.group(1); int index = Integer.parseInt(matcher.group(2)); System.out.println(matcher.group(0)); - Object value3 = BeanUtils.getProperty(propertyVlaue, name3); - if (value3 != null) { - if (value3 instanceof Collection) { - ArrayList values = new ArrayList(); - Iterator items = ((Collection) value).iterator(); - while (items.hasNext()) { - Object item = items.next(); - if (item == null) { - values.add(null); - } else { - values.add(item); - } - } - BeanUtils.setProperty(propertyVlaue, name3,values); - } else if (value.getClass().isArray()) { - int length = Array.getLength(value); - Object[] results = new Object[length]; - for (int i = 0; i < length; i++) { - Object item = Array.get(value, i); - if (item == null) { - results[i] = null; - } else { - results[i] = item; - } - } - BeanUtils.setProperty(propertyVlaue, name3,results); - } else { - BeanUtils.setProperty(propertyVlaue, name3,value); + Object current = getPropertyUtils().getProperty(propertyVlaue, name3); + Class fieldType = getPropertyUtils().getPropertyType(propertyVlaue, name3); + if (fieldType != null && fieldType.isArray()) { + int length = current == null ? 0 : Array.getLength(current); + Object array = Array.newInstance(fieldType.getComponentType(), Math.max(length, index + 1)); + if (length > 0) { + System.arraycopy(current, 0, array, 0, length); } - } + Array.set(array, index, value); + getPropertyUtils().setProperty(propertyVlaue, name3, array); + } else if (current instanceof List) { + List list = (List) current; + while (list.size() <= index) { + list.add(null); + } + list.set(index, value); + } else { + BeanUtils.setProperty(propertyVlaue, name2, value); + } } else { BeanUtils.setProperty(propertyVlaue,name2,value); } From 5ae1a13c0445658db7b377b9d1fbdd62f35919e9 Mon Sep 17 00:00:00 2001 From: Loong Wan Date: Sat, 31 Oct 2026 22:00:52 +0800 Subject: [PATCH 04/20] test: make assertions independent of host files and network --- .../src/test/java/hitool/core/io/utils/FiletypeUtils_Test.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hitool-core/src/test/java/hitool/core/io/utils/FiletypeUtils_Test.java b/hitool-core/src/test/java/hitool/core/io/utils/FiletypeUtils_Test.java index 03eecd7..ac33ee9 100644 --- a/hitool-core/src/test/java/hitool/core/io/utils/FiletypeUtils_Test.java +++ b/hitool-core/src/test/java/hitool/core/io/utils/FiletypeUtils_Test.java @@ -11,7 +11,8 @@ public class FiletypeUtils_Test extends TestCase { public void testname() throws Exception { - assertSame(FiletypeUtils.getFileType(new File("D://cos.jar")), "jar"); + byte[] jarHeader = new byte[] {0x50, 0x4B, 0x03, 0x04, 0x0A, 0, 0, 0, 0, 0, 0}; + assertEquals("jar", FiletypeUtils.getFileType(jarHeader)); } From a137bfe535eed2379b822e4b74f4c197d5b4a295 Mon Sep 17 00:00:00 2001 From: Loong Wan Date: Sat, 31 Oct 2026 22:00:56 +0800 Subject: [PATCH 05/20] test: make assertions independent of host files and network --- .../java/hitool/core/beanutils/BeanPropertyUtilsTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hitool-core/src/test/java/hitool/core/beanutils/BeanPropertyUtilsTest.java b/hitool-core/src/test/java/hitool/core/beanutils/BeanPropertyUtilsTest.java index 9890d29..94adcd0 100644 --- a/hitool-core/src/test/java/hitool/core/beanutils/BeanPropertyUtilsTest.java +++ b/hitool-core/src/test/java/hitool/core/beanutils/BeanPropertyUtilsTest.java @@ -36,8 +36,8 @@ public void testUtils() { BeanPropertyUtils.populate(entity, source, true); // System.out.println(entity.getMethodName()); System.out.println("===========================RESULT================================"); - System.out.println(entity.getProxyBean().getArray()[0]); - System.out.println("proxyBean.proxyBean.methodName:"+entity.getProxyBean().getProxyBean().getMethodName()); + org.junit.Assert.assertEquals("测试名称1", entity.getProxyBean().getArray()[1]); + org.junit.Assert.assertEquals("测试名称1", entity.getProxyBean().getProxyBean().getMethodName()); } From 7afd4007ef02f5a717261037784cde5752409021 Mon Sep 17 00:00:00 2001 From: Loong Wan Date: Sat, 31 Oct 2026 22:01:00 +0800 Subject: [PATCH 06/20] test: make assertions independent of host files and network --- .../src/test/java/hitool/core/lang3/MacAddressUtils_Test.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hitool-core/src/test/java/hitool/core/lang3/MacAddressUtils_Test.java b/hitool-core/src/test/java/hitool/core/lang3/MacAddressUtils_Test.java index dad259f..f3bdcbc 100644 --- a/hitool-core/src/test/java/hitool/core/lang3/MacAddressUtils_Test.java +++ b/hitool-core/src/test/java/hitool/core/lang3/MacAddressUtils_Test.java @@ -21,7 +21,7 @@ public void testRemoteMacAddr_4() { } public void testRemoteMacAddr_3() { - System.out.println("HostMacAddress is : " + MacAddressUtils.getHostMacAddress("192.168.31.1")); + assertNull(MacAddressUtils.getHostMacAddress("127.0.0.1")); } } From bf657f3807927716aedfdf421e33dea68e59933d Mon Sep 17 00:00:00 2001 From: Loong Wan Date: Sat, 31 Oct 2026 22:01:14 +0800 Subject: [PATCH 07/20] test: use temporary files for compression round trips --- .../test/java/hitool/core/compress/GZipUtilsTest.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/hitool-core/src/test/java/hitool/core/compress/GZipUtilsTest.java b/hitool-core/src/test/java/hitool/core/compress/GZipUtilsTest.java index 81591eb..24c0b2b 100644 --- a/hitool-core/src/test/java/hitool/core/compress/GZipUtilsTest.java +++ b/hitool-core/src/test/java/hitool/core/compress/GZipUtilsTest.java @@ -38,17 +38,20 @@ public final void testDataCompress() throws Exception { @Test public final void testFileCompress() throws Exception { - FileOutputStream fos = new FileOutputStream("d:/f.txt"); + File inputFile = File.createTempFile("hitool-compress-", ".txt"); + inputFile.deleteOnExit(); + new File(inputFile.getAbsolutePath() + ".gz").deleteOnExit(); + FileOutputStream fos = new FileOutputStream(inputFile); fos.write(inputStr.getBytes()); fos.flush(); fos.close(); - GZipUtils.compress("d:/f.txt", false); + GZipUtils.compress(inputFile.getAbsolutePath(), false); - GZipUtils.decompress("d:/f.txt.gz", false); + GZipUtils.decompress(inputFile.getAbsolutePath() + ".gz", false); - File file = new File("d:/f.txt"); + File file = new File(inputFile.getAbsolutePath()); FileInputStream fis = new FileInputStream(file); From 92a83599a450aebe51d422f78fb6312576647901 Mon Sep 17 00:00:00 2001 From: Loong Wan Date: Sat, 31 Oct 2026 22:01:17 +0800 Subject: [PATCH 08/20] test: use temporary files for compression round trips --- .../java/hitool/core/compress/BZip2UtilsTest.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/hitool-core/src/test/java/hitool/core/compress/BZip2UtilsTest.java b/hitool-core/src/test/java/hitool/core/compress/BZip2UtilsTest.java index d91cbbd..ca86015 100644 --- a/hitool-core/src/test/java/hitool/core/compress/BZip2UtilsTest.java +++ b/hitool-core/src/test/java/hitool/core/compress/BZip2UtilsTest.java @@ -36,17 +36,20 @@ public final void testDataCompress() throws Exception { @Test public final void testFileCompress() throws Exception { - FileOutputStream fos = new FileOutputStream("d:/f.txt"); + File inputFile = File.createTempFile("hitool-compress-", ".txt"); + inputFile.deleteOnExit(); + new File(inputFile.getAbsolutePath() + ".bz2").deleteOnExit(); + FileOutputStream fos = new FileOutputStream(inputFile); fos.write(inputStr.getBytes()); fos.flush(); fos.close(); - BZip2Utils.compress("d:/f.txt"); + BZip2Utils.compress(inputFile.getAbsolutePath()); - BZip2Utils.decompress("d:/f.txt.bz2"); + BZip2Utils.decompress(inputFile.getAbsolutePath() + ".bz2"); - File file = new File("d:/f.txt"); + File file = new File(inputFile.getAbsolutePath()); FileInputStream fis = new FileInputStream(file); From 0b919ee452e95818fe214809d3d3f6932f51d33a Mon Sep 17 00:00:00 2001 From: Loong Wan Date: Sat, 31 Oct 2026 22:03:31 +0800 Subject: [PATCH 09/20] fix: preserve source filename in compression round trips --- hitool-core/src/main/java/hitool/core/compress/GZipUtils.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hitool-core/src/main/java/hitool/core/compress/GZipUtils.java b/hitool-core/src/main/java/hitool/core/compress/GZipUtils.java index 70670ec..391b0bb 100644 --- a/hitool-core/src/main/java/hitool/core/compress/GZipUtils.java +++ b/hitool-core/src/main/java/hitool/core/compress/GZipUtils.java @@ -80,7 +80,7 @@ public static void compress(File file) throws IOException { * @throws Exception */ public static void compress(File srcFile, boolean delete) throws IOException { - File destFile = new File(srcFile.getParentFile(), FilenameUtils.getBaseName(srcFile.getName()) + EXT); + File destFile = new File(srcFile.getParentFile(), srcFile.getName() + EXT); // 压缩 GZipUtils.compress(srcFile, destFile); if (delete) { @@ -193,7 +193,7 @@ public static void decompress(File srcFile, boolean delete) throws IOException { } public static void decompress(File srcFile, File destDir) throws IOException { - File destFile = new File(destDir, FilenameUtils.getBaseName(srcFile.getName()) + EXT); + File destFile = new File(destDir, FilenameUtils.getBaseName(srcFile.getName())); try (InputStream input = new FileInputStream(srcFile); OutputStream output = new FileOutputStream(destFile);){ GZipUtils.decompress(input, output); From e2c3e84ac2554af8a5b69ae8c314b8f72418b0a3 Mon Sep 17 00:00:00 2001 From: Loong Wan Date: Sat, 31 Oct 2026 22:03:36 +0800 Subject: [PATCH 10/20] fix: preserve source filename in compression round trips --- .../src/main/java/hitool/core/compress/BZip2Utils.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hitool-core/src/main/java/hitool/core/compress/BZip2Utils.java b/hitool-core/src/main/java/hitool/core/compress/BZip2Utils.java index 0500a83..5534a64 100644 --- a/hitool-core/src/main/java/hitool/core/compress/BZip2Utils.java +++ b/hitool-core/src/main/java/hitool/core/compress/BZip2Utils.java @@ -82,7 +82,7 @@ public static void compress(File file) throws IOException { * @throws Exception */ public static void compress(File srcFile, boolean delete) throws IOException { - File destFile = new File(srcFile.getParentFile(), FilenameUtils.getBaseName(srcFile.getName()) + EXT); + File destFile = new File(srcFile.getParentFile(), srcFile.getName() + EXT); // 压缩 BZip2Utils.compress(srcFile, destFile); if (delete) { @@ -175,7 +175,7 @@ public static void decompress(File srcFile, boolean delete) throws IOException { } public static void decompress(File srcFile, File destDir) throws IOException { - File destFile = new File(destDir, FilenameUtils.getBaseName(srcFile.getName()) + EXT); + File destFile = new File(destDir, FilenameUtils.getBaseName(srcFile.getName())); try(InputStream input = new FileInputStream(srcFile); OutputStream output = new FileOutputStream(destFile);) { BZip2Utils.decompress(input, output); From 42bd0a8ad75ca68d566250ccf5da515eda3aa10e Mon Sep 17 00:00:00 2001 From: Loong Wan Date: Sat, 31 Oct 2026 22:03:53 +0800 Subject: [PATCH 11/20] build: package file type signatures as runtime resource --- .../hitool/core/io/fileTypes.properties | 215 ++++++++++++++++++ 1 file changed, 215 insertions(+) create mode 100644 hitool-core/src/main/resources/hitool/core/io/fileTypes.properties diff --git a/hitool-core/src/main/resources/hitool/core/io/fileTypes.properties b/hitool-core/src/main/resources/hitool/core/io/fileTypes.properties new file mode 100644 index 0000000..851fe62 --- /dev/null +++ b/hitool-core/src/main/resources/hitool/core/io/fileTypes.properties @@ -0,0 +1,215 @@ +# 常见文件头信息(该文件中的文件头需要为大写) + +#JPEG (jpg) +FFD8FFE000104A464946=jpg +#PNG (png) +89504E470D0A1A0A0000=png +#GIF (gif) +47494638396126026F01=gif +#TIFF (tif) +49492A00227105008037=tif +#16色位图(bmp) +424D228C010000000000=bmp +#24位位图(bmp) +424D8240090000000000=bmp +#256色位图(bmp) +424D8E1B030000000000=bmp +#CAD (dwg) +41433130313500000000=dwg +#HTML (html) +3C21444F435459504520=html +#HTM (htm) +3C21646F637479706520=htm +#css +48544D4C207B0D0A0942=css +#js +696B2E71623D696B2E71=js +#Rich Text Format (rtf) +7B5C727466315C616E73=rtf +#Photoshop (psd) +38425053000100000000=psd +#Email [Outlook Express 6] (eml) +46726F6D3A203D3F6762=eml +#MS Excel 注意:word、msi 和 excel的文件头一样 +D0CF11E0A1B11AE10000=doc +#Visio 绘图 +D0CF11E0A1B11AE10000=vsd +#MS Access (mdb) +5374616E64617264204A=mdb +252150532D41646F6265=ps +#Adobe Acrobat (pdf) +255044462D312E350D0A=pdf +#rmvb/rm相同 +2E524D46000000120001=rmvb +#flv与f4v相同 +464C5601050000000900=flv +00000020667479706D70=mp4 +49443303000000002176=mp3 +000001BA210001000180=mpg +#wmv与asf相同 +3026B2758E66CF11A6D9=wmv +#Wave (wav) +52494646E27807005741=wav +52494646D07D60074156=avi +#MIDI (mid) +4D546864000000060001=mid +504B0304140000000800=zip +526172211A0700CF9073=rar +235468697320636F6E66=ini +504B03040A0000000000=jar +#可执行文件 +4D5A9000030000000400=exe +#jsp文件 +3C25402070616765206C=jsp +#MF文件 +4D616E69666573742D56=mf +#xml文件 +3C3F786D6C2076657273=xml +#sql文件 +494E5345525420494E54=sql +#java文件 +7061636B616765207765=java +#bat文件 +406563686F206F66660D=bat +#gz文件 +1F8B0800000000000000=gz +#bat文件 +6C6F67346A2E726F6F74=properties +CAFEBABE0000002E0041=class +49545346030000006000=chm +04000000010000001300=mxp +#docx文件 +504B0304140006000800=docx +#WPS文字wps、表格et、演示dps都是一样的 +D0CF11E0A1B11AE10000=wps +6431303A637265617465=torrent + +#Quicktime (mov) +6D6F6F76=mov +#WordPerfect (wpd) +FF575043=wpd +#Outlook Express (dbx) +CFAD12FEC5FD746F=dbx +#Outlook (pst) +2142444E=pst +#Quicken (qdf) +AC9EBD8F=qdf +#Windows Password (pwl) +E3828596=pwl +#Real Audio (ram) +2E7261FD=ram + +#五字节文件头对应关系 + +255044=PDF +526563=EML +D0CF11=PPT +4D5AEE=COM +E93B03=COM +4D5A90=EXE +424D3E=BMP +49492A=TIF +384250=PSD +C5D0D3=EPS +0A0501=PCS +89504E=PNG +060500=RAW +000002=TGA +60EA27=ARJ +526172=RAR +504B03=ZIP +495363=CAB +1F9D8C=Z +524946=WAV +435753=SWF +3026B2=WMV +3026B2=WMA +2E524D=RM +00000F=MOV +000077=MOV +000001=MPA +FFFB50=MP3 +234558=m3u +3C2144=HTM +FFFE3C=XSL +3C3F78=XML +3C3F78=MSC +4C0000=LNK +495453=CHM +805343=scm +D0CF11=XLS +31BE00=WRI +00FFFF=MDF +4D4544=MDS +5B436C=CCD +00FFFF=IMG +FFFFFF=SUB +17A150=PCB +2A5052=ECO +526563=PPC +000100=DDB +42494C=LDB +2A7665=SCH +2A2420=LIB +434841=FNT +7B5C72=RTF +7B5072=GTD +234445=PRG +000007=PJT +202020=BAS +000002=TAG +4D5A90=dll +4D5A90=OCX +4D5A50=DPL +3F5F03=HLP +4D5A90=OLB +4D5A90=IMM +4D5A90=IME +3F5F03=LHP +C22020=NLS +5B5769=CPX +4D5A16=DRV +5B4144=PBK +24536F=PLL +4E4553=NES +87F53E=GBC +00FFFF=SMD +584245=XBE +005001=XMV +000100=TTF +484802=PDG +000100=tst +414331=dwg +D0CF11=max + +#特殊情况下的文件头 + +#images +FFD8FF=jpg +89504E47=png +47494638=gif +49492A00=tif +424D=bmp +#CAD +41433130=dwg +38425053=psd +7B5C727466=rtf +3C3F786D6C=xml +68746D6C3E=html +44656C69766572792D646174653A=eml +D0CF11E0=doc +5374616E64617264204A=mdb +252150532D41646F6265=ps +255044462D312E=pdf +504B0304=zip +52617221=rar +57415645=wav +41564920=avi +2E524D46=rm +000001BA=mpg +000001B3=mpg +6D6F6F76=mov +3026B2758E66CF11=asf +4D546864=mid +1F8B08=gz + From 0485ed6f86362d828856385c699cb093b8bde4e6 Mon Sep 17 00:00:00 2001 From: Loong Wan Date: Sat, 31 Oct 2026 22:03:57 +0800 Subject: [PATCH 12/20] build: remove unbundled file type signatures --- .../java/hitool/core/io/fileTypes.properties | 215 ------------------ 1 file changed, 215 deletions(-) delete mode 100644 hitool-core/src/main/java/hitool/core/io/fileTypes.properties diff --git a/hitool-core/src/main/java/hitool/core/io/fileTypes.properties b/hitool-core/src/main/java/hitool/core/io/fileTypes.properties deleted file mode 100644 index 851fe62..0000000 --- a/hitool-core/src/main/java/hitool/core/io/fileTypes.properties +++ /dev/null @@ -1,215 +0,0 @@ -# 常见文件头信息(该文件中的文件头需要为大写) - -#JPEG (jpg) -FFD8FFE000104A464946=jpg -#PNG (png) -89504E470D0A1A0A0000=png -#GIF (gif) -47494638396126026F01=gif -#TIFF (tif) -49492A00227105008037=tif -#16色位图(bmp) -424D228C010000000000=bmp -#24位位图(bmp) -424D8240090000000000=bmp -#256色位图(bmp) -424D8E1B030000000000=bmp -#CAD (dwg) -41433130313500000000=dwg -#HTML (html) -3C21444F435459504520=html -#HTM (htm) -3C21646F637479706520=htm -#css -48544D4C207B0D0A0942=css -#js -696B2E71623D696B2E71=js -#Rich Text Format (rtf) -7B5C727466315C616E73=rtf -#Photoshop (psd) -38425053000100000000=psd -#Email [Outlook Express 6] (eml) -46726F6D3A203D3F6762=eml -#MS Excel 注意:word、msi 和 excel的文件头一样 -D0CF11E0A1B11AE10000=doc -#Visio 绘图 -D0CF11E0A1B11AE10000=vsd -#MS Access (mdb) -5374616E64617264204A=mdb -252150532D41646F6265=ps -#Adobe Acrobat (pdf) -255044462D312E350D0A=pdf -#rmvb/rm相同 -2E524D46000000120001=rmvb -#flv与f4v相同 -464C5601050000000900=flv -00000020667479706D70=mp4 -49443303000000002176=mp3 -000001BA210001000180=mpg -#wmv与asf相同 -3026B2758E66CF11A6D9=wmv -#Wave (wav) -52494646E27807005741=wav -52494646D07D60074156=avi -#MIDI (mid) -4D546864000000060001=mid -504B0304140000000800=zip -526172211A0700CF9073=rar -235468697320636F6E66=ini -504B03040A0000000000=jar -#可执行文件 -4D5A9000030000000400=exe -#jsp文件 -3C25402070616765206C=jsp -#MF文件 -4D616E69666573742D56=mf -#xml文件 -3C3F786D6C2076657273=xml -#sql文件 -494E5345525420494E54=sql -#java文件 -7061636B616765207765=java -#bat文件 -406563686F206F66660D=bat -#gz文件 -1F8B0800000000000000=gz -#bat文件 -6C6F67346A2E726F6F74=properties -CAFEBABE0000002E0041=class -49545346030000006000=chm -04000000010000001300=mxp -#docx文件 -504B0304140006000800=docx -#WPS文字wps、表格et、演示dps都是一样的 -D0CF11E0A1B11AE10000=wps -6431303A637265617465=torrent - -#Quicktime (mov) -6D6F6F76=mov -#WordPerfect (wpd) -FF575043=wpd -#Outlook Express (dbx) -CFAD12FEC5FD746F=dbx -#Outlook (pst) -2142444E=pst -#Quicken (qdf) -AC9EBD8F=qdf -#Windows Password (pwl) -E3828596=pwl -#Real Audio (ram) -2E7261FD=ram - -#五字节文件头对应关系 - -255044=PDF -526563=EML -D0CF11=PPT -4D5AEE=COM -E93B03=COM -4D5A90=EXE -424D3E=BMP -49492A=TIF -384250=PSD -C5D0D3=EPS -0A0501=PCS -89504E=PNG -060500=RAW -000002=TGA -60EA27=ARJ -526172=RAR -504B03=ZIP -495363=CAB -1F9D8C=Z -524946=WAV -435753=SWF -3026B2=WMV -3026B2=WMA -2E524D=RM -00000F=MOV -000077=MOV -000001=MPA -FFFB50=MP3 -234558=m3u -3C2144=HTM -FFFE3C=XSL -3C3F78=XML -3C3F78=MSC -4C0000=LNK -495453=CHM -805343=scm -D0CF11=XLS -31BE00=WRI -00FFFF=MDF -4D4544=MDS -5B436C=CCD -00FFFF=IMG -FFFFFF=SUB -17A150=PCB -2A5052=ECO -526563=PPC -000100=DDB -42494C=LDB -2A7665=SCH -2A2420=LIB -434841=FNT -7B5C72=RTF -7B5072=GTD -234445=PRG -000007=PJT -202020=BAS -000002=TAG -4D5A90=dll -4D5A90=OCX -4D5A50=DPL -3F5F03=HLP -4D5A90=OLB -4D5A90=IMM -4D5A90=IME -3F5F03=LHP -C22020=NLS -5B5769=CPX -4D5A16=DRV -5B4144=PBK -24536F=PLL -4E4553=NES -87F53E=GBC -00FFFF=SMD -584245=XBE -005001=XMV -000100=TTF -484802=PDG -000100=tst -414331=dwg -D0CF11=max - -#特殊情况下的文件头 - -#images -FFD8FF=jpg -89504E47=png -47494638=gif -49492A00=tif -424D=bmp -#CAD -41433130=dwg -38425053=psd -7B5C727466=rtf -3C3F786D6C=xml -68746D6C3E=html -44656C69766572792D646174653A=eml -D0CF11E0=doc -5374616E64617264204A=mdb -252150532D41646F6265=ps -255044462D312E=pdf -504B0304=zip -52617221=rar -57415645=wav -41564920=avi -2E524D46=rm -000001BA=mpg -000001B3=mpg -6D6F6F76=mov -3026B2758E66CF11=asf -4D546864=mid -1F8B08=gz - From fd816f0a64c254ed1eba8f2026d49619b005cad3 Mon Sep 17 00:00:00 2001 From: Loong Wan Date: Sat, 31 Oct 2026 22:11:25 +0800 Subject: [PATCH 13/20] test: add loopback SMTP server for mail client tests --- .../java/hitool/mail/LocalSmtpServer.java | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 hitool-mail/src/test/java/hitool/mail/LocalSmtpServer.java diff --git a/hitool-mail/src/test/java/hitool/mail/LocalSmtpServer.java b/hitool-mail/src/test/java/hitool/mail/LocalSmtpServer.java new file mode 100644 index 0000000..969d5c9 --- /dev/null +++ b/hitool-mail/src/test/java/hitool/mail/LocalSmtpServer.java @@ -0,0 +1,83 @@ +package hitool.mail; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +final class LocalSmtpServer implements AutoCloseable { + private final ServerSocket server; + private final CountDownLatch received = new CountDownLatch(1); + private final Thread worker; + private volatile String message; + + LocalSmtpServer() throws IOException { + server = new ServerSocket(0, 1, InetAddress.getLoopbackAddress()); + server.setSoTimeout(10000); + worker = new Thread(this::serve, "hitool-test-smtp"); + worker.setDaemon(true); + worker.start(); + } + + int port() { + return server.getLocalPort(); + } + + String awaitMessage() throws InterruptedException { + if (!received.await(5, TimeUnit.SECONDS)) { + throw new AssertionError("No message reached the local SMTP server"); + } + return message; + } + + private void serve() { + try (Socket socket = server.accept(); + BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8)); + PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) { + socket.setSoTimeout(10000); + out.print("220 localhost ESMTP\r\n"); + out.flush(); + String line; + while ((line = in.readLine()) != null) { + if (line.startsWith("EHLO") || line.startsWith("HELO")) { + out.print("250 localhost\r\n"); + } else if (line.equals("DATA")) { + out.print("354 End data with .\r\n"); + out.flush(); + StringBuilder data = new StringBuilder(); + while ((line = in.readLine()) != null && !line.equals(".")) { + data.append(line).append('\n'); + } + message = data.toString(); + received.countDown(); + out.print("250 Message accepted\r\n"); + } else if (line.equals("QUIT")) { + out.print("221 Bye\r\n"); + out.flush(); + break; + } else { + out.print("250 OK\r\n"); + } + out.flush(); + } + } catch (IOException e) { + // The assertion in awaitMessage reports a failed exchange. + } + } + + @Override + public void close() throws IOException { + server.close(); + try { + worker.join(1000); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } +} From 987e32a25d208dbb90e86db810eefbab2c7c9ead Mon Sep 17 00:00:00 2001 From: Loong Wan Date: Sat, 31 Oct 2026 22:11:35 +0800 Subject: [PATCH 14/20] build: retain Spring Mail runtime dependencies --- hitool-mail/pom.xml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/hitool-mail/pom.xml b/hitool-mail/pom.xml index 24114c6..fcfa2aa 100644 --- a/hitool-mail/pom.xml +++ b/hitool-mail/pom.xml @@ -81,16 +81,6 @@ spring-context-support true provided - - - spring-beans - org.springframework - - - spring-context - org.springframework - - From 0d441b92632fd7ee66686277bec3d02f5ab791f4 Mon Sep 17 00:00:00 2001 From: Loong Wan Date: Sat, 31 Oct 2026 22:11:45 +0800 Subject: [PATCH 15/20] fix: avoid passing empty recipient lists to Commons Email --- .../main/java/hitool/mail/def/CommonsMailClientImpl.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hitool-mail/src/main/java/hitool/mail/def/CommonsMailClientImpl.java b/hitool-mail/src/main/java/hitool/mail/def/CommonsMailClientImpl.java index db47cdb..696d444 100644 --- a/hitool-mail/src/main/java/hitool/mail/def/CommonsMailClientImpl.java +++ b/hitool-mail/src/main/java/hitool/mail/def/CommonsMailClientImpl.java @@ -127,7 +127,7 @@ protected void sendMail(EmailBody email,boolean isHtml) throws Exception{ } // 设置收件人的名片和地址 - if(email.getMailto() != null){ + if(email.getMailto() != null && !email.getMailto().isEmpty()){ List mailtoList = new ArrayList(); for (String mailto : email.getMailto().keySet()) { // 添加一个收件人 @@ -138,7 +138,7 @@ protected void sendMail(EmailBody email,boolean isHtml) throws Exception{ } // 设置抄送的名片和地址 - if(email.getMailcc() != null){ + if(email.getMailcc() != null && !email.getMailcc().isEmpty()){ List mailccList = new ArrayList(); for (String mailcc : email.getMailcc().keySet()) { // 添加一个抄送 @@ -149,7 +149,7 @@ protected void sendMail(EmailBody email,boolean isHtml) throws Exception{ } // 设置密送的名片和地址 - if(email.getMailBcc() != null){ + if(email.getMailBcc() != null && !email.getMailBcc().isEmpty()){ List mailBccList = new ArrayList(); for (String mailcc : email.getMailBcc().keySet()) { // 添加一个密送 From 4d85e9c3d9c66cdaf4d3e35eaa665ebfca34c0cd Mon Sep 17 00:00:00 2001 From: Loong Wan Date: Sat, 31 Oct 2026 22:12:09 +0800 Subject: [PATCH 16/20] test: verify mail delivery against local SMTP server --- .../hitool/mail/SpringMailClientTest.java | 123 +++++------------- 1 file changed, 32 insertions(+), 91 deletions(-) diff --git a/hitool-mail/src/test/java/hitool/mail/SpringMailClientTest.java b/hitool-mail/src/test/java/hitool/mail/SpringMailClientTest.java index aee0bc9..b6335b9 100644 --- a/hitool-mail/src/test/java/hitool/mail/SpringMailClientTest.java +++ b/hitool-mail/src/test/java/hitool/mail/SpringMailClientTest.java @@ -2,7 +2,6 @@ import hitool.mail.conf.EmailBody; import hitool.mail.def.SpringMailClientImpl; -import hitool.mail.provider.EmailPropertiesProvider; import hitool.mail.provider.def.DefaultEmailPropertiesProvider; import org.junit.After; import org.junit.Before; @@ -11,98 +10,40 @@ import java.util.Properties; +import static org.junit.Assert.assertTrue; + public class SpringMailClientTest { + private LocalSmtpServer smtp; + private SpringMailClientImpl mailClient; - protected Properties props = System.getProperties(); - protected EmailPropertiesProvider propsProvider; - protected SpringMailClientImpl mailClient; - - @Before - public void setup(){ - - - /* - * 我们是没办法使用javamail通过一般的代理服务器发送邮件的,比如下面的代码是没有效果的: - */ - /*Properties props = System.getProperties(); - props.setProperty("proxySet","true"); - props.setProperty("ProxyHost","192.168.155.1"); - props.setProperty("ProxyPort","1080");*/ - //或者这样,也是没用 - /*Properties props = System.getProperties(); - props.setProperty("proxySet","true"); - props.setProperty("http.proxyHost","192.168.155.1"); - props.setProperty("http.proxyPort","808");*/ + @Before + public void setup() throws Exception { + smtp = new LocalSmtpServer(); + Properties props = new Properties(); + props.setProperty(JavaMailKey.MAIL_HOST, "127.0.0.1"); + props.setProperty(JavaMailKey.MAIL_PORT, Integer.toString(smtp.port())); + props.setProperty(JavaMailKey.MAIL_USER, "sender@example.test"); + props.setProperty(JavaMailKey.MAIL_SMTP_AUTH, "false"); + DefaultEmailPropertiesProvider provider = new DefaultEmailPropertiesProvider(); + provider.setProps(props); + mailClient = new SpringMailClientImpl(); + mailClient.setMailSender(new JavaMailSenderImpl()); + mailClient.setPropsProvider(provider); + } - /* - * 不过可以通过socks网关来访问外网的email服务器,当然,前提是你安装了一个socks服务器 - * 此处使用ccproxy代理测试 - */ - - // 设置代理服务器 - //props.setProperty("proxySet", "true"); - //props.setProperty("socksProxyHost", "10.71.19.215"); - //props.setProperty("socksProxyPort", "1080"); - - //props.setProperty("mail.smtp.host", "smtp.163.com"); - //props.setProperty("mail.smtp.port", "465"); - - - props.put(JavaMailKey.MAIL_DEBUG, "true"); - props.setProperty(JavaMailKey.MAIL_HOST, "smtp.163.com"); - props.setProperty(JavaMailKey.MAIL_PORT, "25"); - props.setProperty(JavaMailKey.MAIL_USER, "xxx@163.com"); - props.setProperty(JavaMailKey.MAIL_PASSWORD, "xxx"); - - - props.put(JavaMailKey.MAIL_SMTP_AUTH, "true"); - // props.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY); - // props.setProperty("mail.smtp.socketFactory.fallback", "false"); - // props.setProperty("mail.smtp.socketFactory.port", "465"); - - // props.put("mail.store.protocol", "pop3"); - // props.put("mail.transport.protocol", "smtp"); - - mailClient = new SpringMailClientImpl(); - - mailClient.setMailSender(new JavaMailSenderImpl()); - - propsProvider = new DefaultEmailPropertiesProvider(); - - propsProvider.setProps(props); - - mailClient.setPropsProvider(propsProvider); - - - } - - @Test - public void testDelete() throws Exception{ - - //构建邮件对象 - EmailBody email = new EmailBody(); - - // 设置发件人信息 - email.setFrom("xxx-消息中心", props.getProperty(JavaMailKey.MAIL_USER), false); + @Test + public void sendsMimeMessageToLocalServer() throws Exception { + EmailBody email = new EmailBody(); + email.setFrom("Sender", "sender@example.test", false); + email.setMailto("Recipient", "recipient@example.test"); + email.setSubject("Mail client test"); + email.setContent("Hello from Hitool"); + assertTrue(mailClient.sendMime(email)); + assertTrue(smtp.awaitMessage().contains("recipient@example.test")); + } - // 设置收件人的邮箱 - String sendTo = "xxx@qq.com"; - email.setMailto(sendTo, sendTo); - - // 设置邮件标题 - email.setSubject("邮件客户端测试"); - // 设置邮件的内容体 - String content = "如果您收到此邮件说明测试成功。"; - email.setContent(content); - - mailClient.sendMime(email); - - - } - - @After - public void shutdown(){ - - } - + @After + public void shutdown() throws Exception { + smtp.close(); + } } From 0cfb8f3aac061c5fac206efb17db5f71f3e3ae23 Mon Sep 17 00:00:00 2001 From: Loong Wan Date: Sat, 31 Oct 2026 22:12:12 +0800 Subject: [PATCH 17/20] test: verify mail delivery against local SMTP server --- .../hitool/mail/CommonsMailClientTest.java | 128 +++++------------- 1 file changed, 32 insertions(+), 96 deletions(-) diff --git a/hitool-mail/src/test/java/hitool/mail/CommonsMailClientTest.java b/hitool-mail/src/test/java/hitool/mail/CommonsMailClientTest.java index fd7cc36..fef50f5 100644 --- a/hitool-mail/src/test/java/hitool/mail/CommonsMailClientTest.java +++ b/hitool-mail/src/test/java/hitool/mail/CommonsMailClientTest.java @@ -2,7 +2,6 @@ import hitool.mail.conf.EmailBody; import hitool.mail.def.CommonsMailClientImpl; -import hitool.mail.provider.EmailPropertiesProvider; import hitool.mail.provider.def.DefaultEmailPropertiesProvider; import org.junit.After; import org.junit.Before; @@ -10,103 +9,40 @@ import java.util.Properties; +import static org.junit.Assert.assertTrue; + public class CommonsMailClientTest { + private LocalSmtpServer smtp; + private CommonsMailClientImpl mailClient; - protected Properties props = System.getProperties(); - protected EmailPropertiesProvider propsProvider; - protected JavaMailClientAdapter mailClient; - - @Before - public void setup(){ - - - /* - * 我们是没办法使用javamail通过一般的代理服务器发送邮件的,比如下面的代码是没有效果的: - */ - /*Properties props = System.getProperties(); - props.setProperty("proxySet","true"); - props.setProperty("ProxyHost","192.168.155.1"); - props.setProperty("ProxyPort","1080");*/ - //或者这样,也是没用 - /*Properties props = System.getProperties(); - props.setProperty("proxySet","true"); - props.setProperty("http.proxyHost","192.168.155.1"); - props.setProperty("http.proxyPort","808");*/ + @Before + public void setup() throws Exception { + smtp = new LocalSmtpServer(); + Properties props = new Properties(); + props.setProperty(JavaMailKey.MAIL_HOST, "127.0.0.1"); + props.setProperty(JavaMailKey.MAIL_PORT, Integer.toString(smtp.port())); + props.setProperty(JavaMailKey.MAIL_USER, "sender@example.test"); + props.setProperty(JavaMailKey.MAIL_SMTP_AUTH, "false"); + props.setProperty(JavaMailKey.MAIL_SMTP_TIMEOUT, "5"); + DefaultEmailPropertiesProvider provider = new DefaultEmailPropertiesProvider(); + provider.setProps(props); + mailClient = new CommonsMailClientImpl(); + mailClient.setPropsProvider(provider); + } - /* - * 不过可以通过socks网关来访问外网的email服务器,当然,前提是你安装了一个socks服务器 - * 此处使用ccproxy代理测试 - */ - - // 设置代理服务器 - props.setProperty("proxySet", "true"); - props.setProperty("socksProxyHost", "10.71.19.215"); - props.setProperty("socksProxyPort", "1080"); - - //props.setProperty("mail.smtp.host", "smtp.163.com"); - //props.setProperty("mail.smtp.port", "465"); - - - props.put(JavaMailKey.MAIL_DEBUG, "true"); - props.setProperty(JavaMailKey.MAIL_HOST, "smtp.163.com"); - props.setProperty(JavaMailKey.MAIL_PORT, "25"); - //props.setProperty(JavaMailKey.MAIL_USER, "xxx@163.com"); - //props.setProperty(JavaMailKey.MAIL_PASSWORD, "xxx"); - props.setProperty(JavaMailKey.MAIL_USER, "xxx@163.com"); - props.setProperty(JavaMailKey.MAIL_PASSWORD, "xxx"); - //commons-mail需要设置mail.smtp.user和mail.smtp.password,才能正常发送邮件 - props.put(JavaMailKey.MAIL_SMTP_USER, "xxx@163.com"); - props.put(JavaMailKey.MAIL_SMTP_PASSWORD, "xxx"); - props.put(JavaMailKey.MAIL_SMTP_AUTH, "true"); - - - props.put(JavaMailKey.MAIL_SMTP_AUTH, "true"); - // props.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY); - // props.setProperty("mail.smtp.socketFactory.fallback", "false"); - // props.setProperty("mail.smtp.socketFactory.port", "465"); - - // props.put("mail.store.protocol", "pop3"); - // props.put("mail.transport.protocol", "smtp"); - - mailClient = new CommonsMailClientImpl(); - - - propsProvider = new DefaultEmailPropertiesProvider(); - - propsProvider.setProps(props); - - mailClient.setPropsProvider(propsProvider); - - - } - - @Test - public void testDelete() throws Exception{ - - //构建邮件对象 - EmailBody email = new EmailBody(); - - // 设置发件人信息 - email.setFrom("xxx-消息中心", props.getProperty(JavaMailKey.MAIL_USER), false); + @Test + public void sendsMimeMessageToLocalServer() throws Exception { + EmailBody email = new EmailBody(); + email.setFrom("Sender", "sender@example.test", false); + email.setMailto("Recipient", "recipient@example.test"); + email.setSubject("Mail client test"); + email.setContent("Hello from Hitool"); + assertTrue(mailClient.sendMime(email)); + assertTrue(smtp.awaitMessage().contains("recipient@example.test")); + } - // 设置收件人的邮箱 - String sendTo = "xxx@qq.com"; - email.setMailto(sendTo, sendTo); - - // 设置邮件标题 - email.setSubject("邮件客户端测试"); - // 设置邮件的内容体 - String content = "如果您收到此邮件说明测试成功。"; - email.setContent(content); - - mailClient.sendMime(email); - - - } - - @After - public void shutdown(){ - - } - + @After + public void shutdown() throws Exception { + smtp.close(); + } } From c208cad7e88030de11117c29618713f1ddf55f83 Mon Sep 17 00:00:00 2001 From: Loong Wan Date: Sat, 31 Oct 2026 22:16:48 +0800 Subject: [PATCH 18/20] build: provide Jakarta Activation implementation for MIME mail --- hitool-mail/pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hitool-mail/pom.xml b/hitool-mail/pom.xml index fcfa2aa..41149dd 100644 --- a/hitool-mail/pom.xml +++ b/hitool-mail/pom.xml @@ -48,6 +48,12 @@ jakarta.activation jakarta.activation-api + + org.eclipse.angus + angus-activation + 2.0.2 + runtime + com.sun.mail From 99817ae121af9848a3cdda2868a0bc1a6bfa9d04 Mon Sep 17 00:00:00 2001 From: Loong Wan Date: Sat, 31 Oct 2026 22:17:02 +0800 Subject: [PATCH 19/20] test: stop mutating system mail settings and use local SMTP --- .../java/hitool/mail/JavaMailClientTest.java | 121 +++++------------- 1 file changed, 31 insertions(+), 90 deletions(-) diff --git a/hitool-mail/src/test/java/hitool/mail/JavaMailClientTest.java b/hitool-mail/src/test/java/hitool/mail/JavaMailClientTest.java index 874512e..a3e19bc 100644 --- a/hitool-mail/src/test/java/hitool/mail/JavaMailClientTest.java +++ b/hitool-mail/src/test/java/hitool/mail/JavaMailClientTest.java @@ -2,7 +2,6 @@ import hitool.mail.conf.EmailBody; import hitool.mail.def.JavaMailClientImpl; -import hitool.mail.provider.EmailPropertiesProvider; import hitool.mail.provider.def.DefaultEmailPropertiesProvider; import org.junit.After; import org.junit.Before; @@ -10,97 +9,39 @@ import java.util.Properties; +import static org.junit.Assert.assertTrue; + public class JavaMailClientTest { + private LocalSmtpServer smtp; + private JavaMailClientImpl mailClient; - protected Properties props = System.getProperties(); - protected EmailPropertiesProvider propsProvider; - protected JavaMailClientAdapter mailClient; - - @Before - public void setup(){ - - - /* - * 我们是没办法使用javamail通过一般的代理服务器发送邮件的,比如下面的代码是没有效果的: - */ - /*Properties props = System.getProperties(); - props.setProperty("proxySet","true"); - props.setProperty("ProxyHost","192.168.155.1"); - props.setProperty("ProxyPort","1080");*/ - //或者这样,也是没用 - /*Properties props = System.getProperties(); - props.setProperty("proxySet","true"); - props.setProperty("http.proxyHost","192.168.155.1"); - props.setProperty("http.proxyPort","808");*/ + @Before + public void setup() throws Exception { + smtp = new LocalSmtpServer(); + Properties props = new Properties(); + props.setProperty(JavaMailKey.MAIL_HOST, "127.0.0.1"); + props.setProperty(JavaMailKey.MAIL_PORT, Integer.toString(smtp.port())); + props.setProperty(JavaMailKey.MAIL_USER, "sender@example.test"); + props.setProperty(JavaMailKey.MAIL_SMTP_AUTH, "false"); + DefaultEmailPropertiesProvider provider = new DefaultEmailPropertiesProvider(); + provider.setProps(props); + mailClient = new JavaMailClientImpl(); + mailClient.setPropsProvider(provider); + } - /* - * 不过可以通过socks网关来访问外网的email服务器,当然,前提是你安装了一个socks服务器 - * 此处使用ccproxy代理测试 - */ - - // 设置代理服务器 - props.setProperty("proxySet", "true"); - props.setProperty("socksProxyHost", "10.71.19.215"); - props.setProperty("socksProxyPort", "1080"); - - //props.setProperty("mail.smtp.host", "smtp.163.com"); - //props.setProperty("mail.smtp.port", "465"); - - - props.put(JavaMailKey.MAIL_DEBUG, "true"); - props.setProperty(JavaMailKey.MAIL_HOST, "smtp.163.com"); - props.setProperty(JavaMailKey.MAIL_PORT, "25"); - props.setProperty(JavaMailKey.MAIL_USER, "xxx@163.com"); - props.setProperty(JavaMailKey.MAIL_PASSWORD, "xxx"); - - - props.put(JavaMailKey.MAIL_SMTP_AUTH, "true"); - // props.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY); - // props.setProperty("mail.smtp.socketFactory.fallback", "false"); - // props.setProperty("mail.smtp.socketFactory.port", "465"); - - // props.put("mail.store.protocol", "pop3"); - // props.put("mail.transport.protocol", "smtp"); - - mailClient = new JavaMailClientImpl(); - - - propsProvider = new DefaultEmailPropertiesProvider(); - - propsProvider.setProps(props); - - mailClient.setPropsProvider(propsProvider); - - - } - - @Test - public void testDelete() throws Exception{ - - //构建邮件对象 - EmailBody email = new EmailBody(); - - // 设置发件人信息 - email.setFrom("xxx-消息中心", props.getProperty(JavaMailKey.MAIL_USER), false); + @Test + public void sendsMimeMessageToLocalServer() throws Exception { + EmailBody email = new EmailBody(); + email.setFrom("Sender", "sender@example.test", false); + email.setMailto("Recipient", "recipient@example.test"); + email.setSubject("Mail client test"); + email.setContent("Hello from Hitool"); + assertTrue(mailClient.sendMime(email)); + assertTrue(smtp.awaitMessage().contains("recipient@example.test")); + } - // 设置收件人的邮箱 - String sendTo = "xxx@qq.com"; - email.setMailto(sendTo, sendTo); - - // 设置邮件标题 - email.setSubject("邮件客户端测试"); - // 设置邮件的内容体 - String content = "如果您收到此邮件说明测试成功。"; - email.setContent(content); - - mailClient.sendMime(email); - - - } - - @After - public void shutdown(){ - - } - + @After + public void shutdown() throws Exception { + smtp.close(); + } } From 68679cfbad77e36c06f1877a4119cc41f3fb1b6c Mon Sep 17 00:00:00 2001 From: Loong Wan Date: Sat, 31 Oct 2026 22:18:29 +0800 Subject: [PATCH 20/20] test: set Jakarta Mail SMTP transport port --- hitool-mail/src/test/java/hitool/mail/JavaMailClientTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/hitool-mail/src/test/java/hitool/mail/JavaMailClientTest.java b/hitool-mail/src/test/java/hitool/mail/JavaMailClientTest.java index a3e19bc..fb9784e 100644 --- a/hitool-mail/src/test/java/hitool/mail/JavaMailClientTest.java +++ b/hitool-mail/src/test/java/hitool/mail/JavaMailClientTest.java @@ -21,6 +21,7 @@ public void setup() throws Exception { Properties props = new Properties(); props.setProperty(JavaMailKey.MAIL_HOST, "127.0.0.1"); props.setProperty(JavaMailKey.MAIL_PORT, Integer.toString(smtp.port())); + props.setProperty(JavaMailKey.MAIL_SMTP_PORT, Integer.toString(smtp.port())); props.setProperty(JavaMailKey.MAIL_USER, "sender@example.test"); props.setProperty(JavaMailKey.MAIL_SMTP_AUTH, "false"); DefaultEmailPropertiesProvider provider = new DefaultEmailPropertiesProvider();