前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >探秘Java批量发邮件

探秘Java批量发邮件

作者头像
不安分的猿人
发布2020-03-02 11:43:29
1.6K0
发布2020-03-02 11:43:29
举报
文章被收录于专栏:不安分的猿人

一、要实现的功能

1.获取通过程序发送邮件的权限(配置即可)

本编以qq邮箱为例,开启POP2/SMTP服务,按照操作,发送短信到指定号码后,页面就返回一串随机密码。将这里的密码保存好。接下来会使用它。

2.通过Java代码实现批量发邮件功能

二、代码实现

1.maven项目引入的依赖如下:

代码语言:javascript
复制
    <dependencies>
        <!-- email -->
        <dependency>
            <groupId>com.sun.mail</groupId>
            <artifactId>javax.mail</artifactId>
            <version>1.5.4</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.4</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.0.4</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.8.1</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-cron</artifactId>
            <version>4.6.4</version>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-email</artifactId>
            <version>1.4</version>
        </dependency>
        <dependency>
            <groupId>dnsjava</groupId>
            <artifactId>dnsjava</artifactId>
            <version>2.1.1</version>
        </dependency>
    </dependencies>

1.从文件中读取qq邮箱

文件文件中的邮箱信息格式如下:

代码语言:javascript
复制
251236160
254923348
269380365
270061097
270371508

代码如下:

代码语言:javascript
复制
 public static List<String> readFileByLines(String filePath) {

        List<String> qqMailList = new ArrayList<>();
        File file = new File(filePath);
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader(file));
            String tempString = null;
            int line = 1;
            // 一次读入一行,直到读入null为文件结束
            while ((tempString = reader.readLine()) != null) {
                qqMailList.add(tempString + "@qq.com");
                line++;
            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e1) {
                }
            }
        }
        return qqMailList;
    }

2.验证邮箱是否有效

验证邮箱是否有效,是通过DNS的MX记录来验证的。

DNS中除了A记录(域名-IP映射)之外,还有MX记录(邮件交换记录),CNAME记录(别名)。MX记录就是为了在发送邮件时使用友好域名规则,比如我们发送到QQ邮箱xxx@qq.com。我们填写地址是到“qq.com”,但实际上可能服务器地址千奇百怪。在设置DNS时可以顺带设置MX记录。

代码如下:

代码语言:javascript
复制
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<Record> arrRecords = new ArrayList<Record>();
                Collections.addAll(arrRecords, mxRecords);
                Collections.sort(arrRecords, new Comparator<Record>() {

                    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: <check@" + domain + ">\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;
    }

3.组装邮件内容

1. 配置发送邮件的基础信息

需要配置发送邮件的基本信息,包括邮箱服务的IP地址,端口号,自己的邮箱地址,邮箱授权密码(第一步在邮箱后台获取的密码)。

2.组装邮件内容

邮件内容包括:收件人信息,抄送人信息,邮件标题,邮件内容,邮件附件等信息

示例代码如下:

代码语言:javascript
复制
public boolean   sendSSLEmailWithCC(List<String> listEmails,  String title, String content ,List<File> attachments) throws NoSuchProviderException, SendFailedException, ParseException,
            MessagingException, NullPointerException, UnsupportedEncodingException {

        LOGGER.info("开始发送邮件,email==>"+listEmails+",title==>"+title);
        Properties props = System.getProperties();
        MailBean mailBean = new MailBean();
        props.put("mail.smtp.host", mailBean.getHost());
        // 指定协议
        props.put("mail.transport.protocol", "smtp");
        props.put("mail.smtp.port", mailBean.getSSLport());
        props.put("mail.smtp.starttls.enable", mailBean.getStarttlsEnable());

        props.put("mail.smtp.auth", mailBean.getAuth());
        props.put("mail.smtp.connectiontimeout", mailBean.getConnectiontimeout());
        props.put("mail.smtp.timeout", mailBean.getTimeout());
        props.put("mail.smtp.debug", true);
        Transport transport = null;
        Session session = Session.getDefaultInstance(props, null);
        transport = session.getTransport("smtp");
        transport.connect(mailBean.getHost(), mailBean.getAccount(), mailBean.getPassword());


        // 组装收件人邮箱
        MimeMessage msg = new MimeMessage(session);
        msg.setSentDate(new Date());
        InternetAddress fromAddress = new InternetAddress(mailBean.getAccount(), nickname);
        msg.setFrom(fromAddress);
        InternetAddress[] toAddress = new InternetAddress[listEmails.size()];
        for(int k = 0;k<listEmails.size();k++){
            String emailAddress = listEmails.get(k);
            new InternetAddress(emailAddress);
            toAddress[k]=new InternetAddress(emailAddress);
        }

        // 向multipart对象中添加邮件的各个部分内容,包括文本内容和附件
        Multipart multipart = new MimeMultipart();
        BodyPart contentPart = new MimeBodyPart();
        contentPart.setContent(content, "text/html; charset=utf-8");
        multipart.addBodyPart(contentPart);

        // 将multipart对象放到message中
        msg.setContent(multipart);

        LOGGER.debug("当前需要发送邮件的地址信息============>{}"+Arrays.deepToString(toAddress));
        msg.addRecipients(Message.RecipientType.TO, toAddress);

        msg.setSubject(title, "UTF-8");
        //发送文本邮件

        transport.sendMessage(msg, msg.getAllRecipients());
        LOGGER.info("邮件已发送");
        return true;
    }

4.批量发送邮件

本地测试我就使用的main方法简单运行了。

示例代码如下:

代码语言:javascript
复制
 /**
     * 移除无法抵达的邮箱
     */
    public static List<String> removeUnreachableEmail(List<String> listEmails){
        List<String> filtedList = new ArrayList<>();
        if(CollectionUtil.isNotEmpty(listEmails)){
            filtedList = listEmails.stream().filter(e -> MailValid.valid(e, "jootmir.org"))
                    .collect(Collectors.toList());
        }
        return filtedList;

    }
    private String nickname ="不安分的猿人";//发送者,显示的发件人名字
    protected static Log LOGGER = LogFactory.getLog(MailUtil.class);

    public static void main(String[] args) throws IOException, MessagingException, NoSuchProviderException,SendFailedException, ParseException {
        MailUtil mailUtil = new MailUtil();
        List<String> listEmails = removeUnreachableEmail(FileUtils.readFileByLines("E:\\下载\\2019-09-02_22-12-07.txt"));
        String emailTile = "珍藏多年的编程资源分享给你!";
        StringBuffer emailContent = new StringBuffer();
        FileUtils.readToBuffer(emailContent,"E:\\下载\\cb8oj-qgbhj.html");
        List<File>  attrachList = new ArrayList<>();
        attrachList.add(new File("E:\\下载\\公众号二维码.jpg"));
        mailUtil.sendSSLEmailWithCC(listEmails, emailTile, emailContent.toString(), attrachList);
    }

三、总结

Java发邮件有很多种方式:

1.使用JavaMail发送邮件

2.Spring Boot中使用JavaMailSender发送邮件

3.开源框架Simple Java Mail

四、FAQ

1.发送无效邮箱的时候,会直接抛出异常。javax.mail.SendFailedException: Invalid Address 与 SMTPAddressFailedException 抛错。

解决方式:在发送邮件前,先校验所有的邮箱是否有效。代码已实现。

参考资料:

1. Java 发送邮件的几种方式

https://blog.csdn.net/qq_32371887/article/details/72821291

2. 使用 javamail 实现发送邮件(QQ邮箱和163邮箱)

https://blog.csdn.net/zouxucong/article/details/60756482

3. Java 与邮件系统交互之使用 Socket 验证邮箱是否存在

https://www.cnblogs.com/Johness/p/javaemail_usesockettocheckemailaddressvalid.html

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-09-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 不安分的猿人 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、要实现的功能
    • 1.获取通过程序发送邮件的权限(配置即可)
      • 2.通过Java代码实现批量发邮件功能
      • 二、代码实现
        • 1.maven项目引入的依赖如下:
          • 1.从文件中读取qq邮箱
            • 2.验证邮箱是否有效
              • 3.组装邮件内容
                • 1. 配置发送邮件的基础信息
                • 2.组装邮件内容
              • 4.批量发送邮件
              • 三、总结
              • 四、FAQ
              • 参考资料:
              相关产品与服务
              短信
              腾讯云短信(Short Message Service,SMS)可为广大企业级用户提供稳定可靠,安全合规的短信触达服务。用户可快速接入,调用 API / SDK 或者通过控制台即可发送,支持发送验证码、通知类短信和营销短信。国内验证短信秒级触达,99%到达率;国际/港澳台短信覆盖全球200+国家/地区,全球多服务站点,稳定可靠。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档