使用JavaMail发送邮件时如何判断收件人邮箱是否有效的解决方案

昨天公司老总提了个需求,要求给用户提供的邮箱发送邮件后,希望能收到反馈,判断是否发送成功。公司的项目是使用JavaMail来给用户发送邮件,但是调用Transport类的sendMessage方法发送邮件是没有返回值的。于是去百度,搜寻了好长时间,终于找到了两篇博客,以为能够解决这个问题,然后就去试了,可结果还是不行。

博客截图如下:

使用JavaMail发送邮件时如何判断收件人邮箱是否有效的解决方案_第1张图片

附上具体的地址:http://www.cnblogs.com/interdrp/p/5912723.html

具体的代码参考我找到的另一篇博客:https://blog.csdn.net/runyon1982/article/details/49018873

 

但是,不管我使用的是否是注册的还是未注册的邮箱,返回的结果都是: MESSAGE_DELIVERED,看了一下评论区的人,发现很多人情况和我都一看,心中充满了郁闷,因为找博客,找完整代码,整合到自己项目中来测试花了很多时间了,但是问题依旧没有解决。不过干咱们这行的,发牢骚、逃避是解决不了问题的,该干的活还是得干,于是调整了心情,我继续想办法。

我分析到:既然是要检验这个邮箱是否是有效的,那么给这个邮箱发一封邮件判断对方是否收到是一种解决方案,但却不是唯一的解决方案,我就想是不是有什么方法可以校验这个邮箱是否真实存在的呢?带着这个疑惑,我更换了在百度上用于搜索的关键字,果然,让我找到了一篇名为《Java与邮件系统交互之使用Socket验证邮箱是否存在》的博文,具体地址是:https://www.cnblogs.com/Johness/p/javaemail_usesockettocheckemailaddressvalid.html

我直接将这篇博客上的代码拷贝到我的项目上,测试了几个有效的邮箱,包括163邮箱,qq邮箱,腾讯企业邮箱,发现打印的结果都是true,然后又测试了几个不存在的邮箱,返回的结果都是false。此刻内心对这个作者充满了感激与膜拜......

 

为了表达对这段代码的喜爱,我特地复制上来跟各位一起欣赏:

package sy.util.sendemail;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.CompareToBuilder;
import org.xbill.DNS.Lookup;
import org.xbill.DNS.MXRecord;
import org.xbill.DNS.Record;
import org.xbill.DNS.TextParseException;
import org.xbill.DNS.Type;


public class MailValid {

    public static void main(String[] args) {
//        System.out.println(new MailValid().valid("[email protected]", "jootmir.org"));

        
    }
    
    /**
     * 验证邮箱是否存在
     * 
* 由于要读取IO,会造成线程阻塞 * * @param toMail * 要验证的邮箱 * @param domain * 发出验证请求的域名(是当前站点的域名,可以任意指定) * @return * 邮箱是否可达 */ public static boolean valid(String toMail, String domain) { if(StringUtils.isBlank(toMail) || StringUtils.isBlank(domain)) return false; if(!StringUtils.contains(toMail, '@')) return false; String host = toMail.substring(toMail.indexOf('@') + 1); if(host.equals(domain)) return false; Socket socket = new Socket(); try { // 查找mx记录 Record[] mxRecords = new Lookup(host, Type.MX).run(); if(ArrayUtils.isEmpty(mxRecords)) return false; // 邮件服务器地址 String mxHost = ((MXRecord)mxRecords[0]).getTarget().toString(); if(mxRecords.length > 1) { // 优先级排序 List arrRecords = new ArrayList(); Collections.addAll(arrRecords, mxRecords); Collections.sort(arrRecords, new Comparator() { public int compare(Record o1, Record o2) { return new CompareToBuilder().append(((MXRecord)o1).getPriority(), ((MXRecord)o2).getPriority()).toComparison(); } }); mxHost = ((MXRecord)arrRecords.get(0)).getTarget().toString(); } // 开始smtp socket.connect(new InetSocketAddress(mxHost, 25)); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new BufferedInputStream(socket.getInputStream()))); BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); // 超时时间(毫秒) long timeout = 6000; // 睡眠时间片段(50毫秒) int sleepSect = 50; // 连接(服务器是否就绪) if(getResponseCode(timeout, sleepSect, bufferedReader) != 220) { return false; } // 握手 bufferedWriter.write("HELO " + domain + "\r\n"); bufferedWriter.flush(); if(getResponseCode(timeout, sleepSect, bufferedReader) != 250) { return false; } // 身份 bufferedWriter.write("MAIL FROM: \r\n"); bufferedWriter.flush(); if(getResponseCode(timeout, sleepSect, bufferedReader) != 250) { return false; } // 验证 bufferedWriter.write("RCPT TO: <" + toMail + ">\r\n"); bufferedWriter.flush(); if(getResponseCode(timeout, sleepSect, bufferedReader) != 250) { return false; } // 断开 bufferedWriter.write("QUIT\r\n"); bufferedWriter.flush(); return true; } catch (NumberFormatException e) { } catch (TextParseException e) { } catch (IOException e) { } catch (InterruptedException e) { } finally { try { socket.close(); } catch (IOException e) { } } return false; } private static int getResponseCode(long timeout, int sleepSect, BufferedReader bufferedReader) throws InterruptedException, NumberFormatException, IOException { int code = 0; for(long i = sleepSect; i < timeout; i += sleepSect) { Thread.sleep(sleepSect); if(bufferedReader.ready()) { String outline = bufferedReader.readLine(); // FIXME 读完…… while(bufferedReader.ready()) /*System.out.println(*/bufferedReader.readLine()/*)*/; /*System.out.println(outline);*/ code = Integer.parseInt(outline.substring(0, 3)); break; } } return code; } }

原博客上的jar包下载链接找不到,附上在Maven Repository中的下载地址:

http://mvnrepository.com/artifact/dnsjava/dnsjava/2.1.1

使用JavaMail发送邮件时如何判断收件人邮箱是否有效的解决方案_第2张图片

 

要是该链接失效了,可以自己到Maven 仓库官网:http://mvnrepository.com/artifact/opensymphony/quartz-all ,输入关键字:dnsjava  搜索,注意选择 dnsjava包下的资源下载,如图:

使用JavaMail发送邮件时如何判断收件人邮箱是否有效的解决方案_第3张图片

 

对找jar包有过非常痛苦的经历,所以稍微啰嗦了一下,哈哈。言归正传,

 

接着,测试了邮箱有效之后,就可以给这个邮箱发邮件了,如果正常发送,说明发送成功了,因为邮箱是有效的,至于是不是用户本人的,那就只有用户自己知道了,如果发送过程中抛了异常,那就说明发送失败。

 

但是,这其实并非真正的解决方案,真正的解决方案是:

(1)如果这个邮箱对用户和对网站自身来说很重要的话,那么在注册的时候就应该强制用户验证邮箱,这样以后发邮箱时就能保证该邮箱是有效的。

(2)对于企业邮箱,有可能用户会因为离职等原因,导致原来的邮箱不可用,或者对于那些用户主动关闭邮箱的情况,就需要调用工具类定时检验邮箱是否可用的。但是我们知道,IO是非常耗费计算机资源的,所以有必要降低IO的频率,同时避免在网站使用的高峰期进行大量的IO操作。

 

至此,问题勉强解决了。如果有更好的方法,欢迎指教。

 

解决方法一直都在,只是没有人将javamail与Socket校验这两个词关联起来,我今天做的,就是关联这两个词,仅此而已。

 

 

 

 

 

你可能感兴趣的:(JavaMail)