Java的Email简单发送与接收

简介

1.本文只针对基础代码解析整理,原理不想过多解释
2.写这篇博客是为了理清思路
3.本文的测试对象为qq邮箱

发送Email

1.发送原理

发送方发送到邮件服务器,接收方从服务器读取内容的过程

流程图

2.协议

1.MUA到MTA发送邮件的协议就是SMTP协议,它是Simple Mail Transport Protocol的缩写
  使用标准端口25,也可以使用加密端口465或587
2.SMTP协议是一个建立在TCP之上的协议,任何程序发送邮件都必须遵守SMTP协议

3.MSTP登录信息

QQ邮箱:SMTP服务器是smtp.qq.com,端口是465/587
163邮箱:SMTP服务器是smtp.163.com,端口是465
Gmail邮箱:SMTP服务器是smtp.gmail.com,端口是465/587

4.实例

1、首先是最简单发送纯文本Email实例

//纯文本发送
public class MailService {
    public static void main(String[] args) throws GeneralSecurityException, MessagingException {
        //创建一个配置文件并保存
        Properties properties = new Properties();

        properties.setProperty("mail.host", "smtp.qq.com"); // SMTP主机名
        properties.setProperty("mail.transport.protocol","smtp");
        properties.setProperty("mail.smtp.auth","true");// 是否需要用户认证

        //QQ存在一个特性设置SSL加密
        MailSSLSocketFactory sf = new MailSSLSocketFactory();
        sf.setTrustAllHosts(true);
        properties.put("mail.smtp.ssl.enable", "true");//开启ssl安全连接
        properties.put("mail.smtp.ssl.socketFactory", sf);

        //创建一个session对象
        Session session = Session.getDefaultInstance(properties, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication("发送方邮箱",
                        "qq邮箱smtp服务授权码");
             //在邮箱的设置-》账户-》POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务中获取
            }
        });

        // 设置debug模式便于调试:
        session.setDebug(true);

        //TODO:构建Message对象
        MimeMessage message = new MimeMessage(session);
        //设置发送方地址:
        try {
            message.setFrom(new InternetAddress("发送方地址"));
        } catch (MessagingException e) {
            e.printStackTrace();
        }
        // 设置接收方地址:
        message.setRecipients(Message.RecipientType.TO,
                String.valueOf(new InternetAddress("接收方地址")));
        //设置邮件主题
        message.setSubject("Hello","UTF-8");
        //设置邮件正文
        message.setText("hello","UTF-8","html")//发送
        Transport.send(message);
    }
}

2、然后是正文有所改变的纯文字HTML代码

//纯文本发送
public class MailService {
    public static void main(String[] args) throws GeneralSecurityException, MessagingException {
        //创建一个配置文件并保存
        Properties properties = new Properties();

        properties.setProperty("mail.host", "smtp.qq.com"); // SMTP主机名
        properties.setProperty("mail.transport.protocol","smtp");
        properties.setProperty("mail.smtp.auth","true");// 是否需要用户认证

        //QQ存在一个特性设置SSL加密
        MailSSLSocketFactory sf = new MailSSLSocketFactory();
        sf.setTrustAllHosts(true);
        properties.put("mail.smtp.ssl.enable", "true");//开启ssl安全连接
        properties.put("mail.smtp.ssl.socketFactory", sf);

        //创建一个session对象
        Session session = Session.getDefaultInstance(properties, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication("发送方邮箱",
                        "qq邮箱smtp服务授权码");
             //在邮箱的设置-》账户-》POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务中获取
            }
        });

        // 设置debug模式便于调试:
        session.setDebug(true);

        //TODO:构建Message对象
        MimeMessage message = new MimeMessage(session);
        //设置发送方地址:
        try {
            message.setFrom(new InternetAddress("发送方地址"));
        } catch (MessagingException e) {
            e.printStackTrace();
        }
        // 设置接收方地址:
        message.setRecipients(Message.RecipientType.TO,
                String.valueOf(new InternetAddress("接收方地址")));
        //设置邮件主题
        message.setSubject("Hello","UTF-8");
        //设置邮件正文
        message.setText("<h1>Hello</h1><p>Hi, xxx</p>","UTF-8","html")//发送
        Transport.send(message);
    }
}

3、添加附件的Email邮件

//纯文本发送
public class MailService {
    public static void main(String[] args) throws GeneralSecurityException, MessagingException {
        //创建一个配置文件并保存
        Properties properties = new Properties();

        properties.setProperty("mail.host", "smtp.qq.com"); // SMTP主机名
        properties.setProperty("mail.transport.protocol","smtp");
        properties.setProperty("mail.smtp.auth","true");// 是否需要用户认证

        //QQ存在一个特性设置SSL加密
        MailSSLSocketFactory sf = new MailSSLSocketFactory();
        sf.setTrustAllHosts(true);
        properties.put("mail.smtp.ssl.enable", "true");//开启ssl安全连接
        properties.put("mail.smtp.ssl.socketFactory", sf);

        //创建一个session对象
        Session session = Session.getDefaultInstance(properties, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication("发送方邮箱",
                        "qq邮箱smtp服务授权码");
             //在邮箱的设置-》账户-》POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务中获取
            }
        });

        // 设置debug模式便于调试:
        session.setDebug(true);

        //TODO:构建Message对象
        MimeMessage message = new MimeMessage(session);
        //设置发送方地址:
        try {
            message.setFrom(new InternetAddress("发送方地址"));
        } catch (MessagingException e) {
            e.printStackTrace();
        }
        // 设置接收方地址:
        message.setRecipients(Message.RecipientType.TO,
                String.valueOf(new InternetAddress("接收方地址")));
        //设置邮件主题
        message.setSubject("Hello","UTF-8");
        //设置邮件正文
        message.setText("hello","UTF-8","html")//Multipart对象包含若干个bodpart
        //bodpart中可以添加各种附件
        Multipart multipart = new MimeMultipart();
        //TODO:添加text
        BodyPart textPart = new MimeBodyPart();
        //数据源
        DataSource dataSource = new FileDataSource(new
                File("D:\\..\\text.txt"));//绝对路径
        //数据处理器
        DataHandler dataHandler = new DataHandler(dataSource);
        //设置第一个附件的数据
        textPart.setDataHandler(dataHandler);
        textPart.setFileName("text");
        multipart.addBodyPart(textPart);

        //TODO:添加image
        BodyPart imagePart = new MimeBodyPart();
        imagePart.setFileName("1.gif");
        imagePart.setDataHandler(new DataHandler(new FileDataSource(new
                File("D:\\..\\preview.gif"))));//绝对路径
        multipart.addBodyPart(imagePart);
        
        //设置邮件内容为multipaet
        message.setContent(multipart);
        
        //发送
        Transport.send(message);
    }
}

测试后邮件正文消失,只包含邮件附件,可能与发送机制有关

4.发送内嵌图片的HTML邮件

注意如果给一个< img src=“http://example.com/test.jpg”>,这样的外部图片链接通常会被邮件客户端过滤,并提示用户显示图片并不安全。只有内嵌的图片才能正常在邮件中显示

//纯文本发送
public class MailService {
    public static void main(String[] args) throws GeneralSecurityException, MessagingException {
        //创建一个配置文件并保存
        Properties properties = new Properties();

        properties.setProperty("mail.host", "smtp.qq.com"); // SMTP主机名
        properties.setProperty("mail.transport.protocol","smtp");
        properties.setProperty("mail.smtp.auth","true");// 是否需要用户认证

        //QQ存在一个特性设置SSL加密
        MailSSLSocketFactory sf = new MailSSLSocketFactory();
        sf.setTrustAllHosts(true);
        properties.put("mail.smtp.ssl.enable", "true");//开启ssl安全连接
        properties.put("mail.smtp.ssl.socketFactory", sf);

        //创建一个session对象
        Session session = Session.getDefaultInstance(properties, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication("发送方邮箱",
                        "qq邮箱smtp服务授权码");
             //在邮箱的设置-》账户-》POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务中获取
            }
        });

        // 设置debug模式便于调试:
        session.setDebug(true);
        
        //Multipart对象包含若干个bodpart
        //bodpart中可以添加各种附件
        //内嵌图片实际上也是一个附件,即邮件本身也是Multipart
        Multipart multipart = new MimeMultipart();

        //TODO:构建Message对象
        MimeMessage message = new MimeMessage(session);
        //设置发送方地址:
        try {
            message.setFrom(new InternetAddress("发送方地址"));
        } catch (MessagingException e) {
            e.printStackTrace();
        }
        // 设置接收方地址:
        message.setRecipients(Message.RecipientType.TO,
                String.valueOf(new InternetAddress("接收方地址")));
        //设置邮件主题
        message.setSubject("Hello","UTF-8");
        //设置邮件正文
        message.setText("<h1>Hello</h1><p>Hi, xxx</p>","UTF-8","html")//TODO:发送内嵌图片的HTML邮件
        Map<String, String> imagesMap = new HashMap<>();
        //采用hashmap可以以满足html表达式
        imagesMap.put("image","D:\\..\\preview.gif");
        // 添加text:
        BodyPart textpart = new MimeBodyPart();
        textpart.setContent(
                "<h1>我老婆发给你了</h1><p><img src=\"cid:image\"></p>",
                "text/html;charset=utf-8");
        multipart.addBodyPart(textpart);
        // 添加image:
        BodyPart imagepart = new MimeBodyPart();
        imagepart.setFileName("1.gif");
        imagepart.setDataHandler(new DataHandler(new FileDataSource(new
                File("D:\\..\\preview.gif"))));
        // 与HTML的<img src="cid:img01">关联:
        imagepart.setHeader("Content-ID", "image");
        multipart.addBodyPart(imagepart);

        //发送
        Transport.send(message);
    }
}

5.小结

1.使用JavaMail API发送邮件本质上是一个MUA软件通过SMTP协议发送邮件至MTA服务器
2.打开调试模式可以看到详细的SMTP交互信息
3.某些邮件服务商需要开启SMTP,并需要独立的SMTP登录密码
4.当然老婆是不会给你们看的

接收Email

1.接收Email就是从MTA服务器读取文件的过程
2.因为qq邮箱应该是有新旧两个文件夹或者其它管理机制,从"INBOX"(一般MTA服务器存放邮件的文件夹)读取的
  邮件都是之前的邮件,到最近的邮件就没有访问成功过,都是抛出异常,小白我估计是触发了某种机制
3.qq邮箱的发送与接收都需要ssl加密

协议特点

1.使用最广泛的协议是POP3:Post Office Protocol version 3
 	  它是一个建立在TCP连接之上的协议
      POP3服务器的标准端口是110,如果整个会话需要加密,那么使用加密端口995
2.另一种接收邮件的协议是IMAP :Internet Mail Access  Protocol
      它使用标准端口143和加密端口993
      IMAP协议在本地的所有操作都会自动同步到服务器上
      IMAP可以允许用户在邮件服务器的收件箱中创建文件夹

实例

一看就懂的那种

//接收邮件
public class MailReceive {
    public static void main(String[] args) throws GeneralSecurityException, MessagingException {
        // 准备登录信息:
        String host = "pop.qq.com";
        int port = 995;
        String username = "发送方邮箱";
        String password = "授权码";

        //创建一个配置文件并保存
        Properties properties = new Properties();
        properties.setProperty("mail.store.protocol", "pop3");// 协议名称
        properties.setProperty("mail.pop3.host",host); // SMTP主机名
        properties.setProperty("mail.pop3.port", String.valueOf(port)); // 端口号
        properties.setProperty("mail.pop3.auth","true");// 是否需要用户认证
        //QQ存在一个特性设置SSL加密,注释掉的和代码也是开启ssl加密的方法
//        props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
//        props.put("mail.smtp.socketFactory.port", String.valueOf(port));
        MailSSLSocketFactory sf = new MailSSLSocketFactory();
        sf.setTrustAllHosts(true);
        properties.put("mail.pop3.ssl.enable", "true");//开启ssl安全连接
        properties.put("mail.pop3.ssl.socketFactory", sf);

        // 连接到Store:
        URLName urlName = new URLName("pop3",host,port,"",username,password);
        Session session = Session.getInstance(properties,null);
        session.setDebug(true);
        Store store = new POP3SSLStore(session,urlName);
        store.connect();

        Folder folder = null;
        try {
            folder = store.getFolder("INBOX");// 获取收件箱:
            folder.open(Folder.READ_WRITE);// 以读写方式打开:
            System.out.println("Total messages: " + folder.getMessageCount());
            System.out.println("New messages: " + folder.getNewMessageCount());
            System.out.println("Unread messages: " + folder.getUnreadMessageCount());
            System.out.println("Deleted messages: " + folder.getDeletedMessageCount());
            Message[] messages = folder.getMessages();
            for (Message message : messages) {
                printMessage((MimeMessage) message);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (folder != null) {
                try {
                    folder.close(true);
                } catch (MessagingException e) {
                    e.printStackTrace();
                }
            }
            if (store != null) {
                try {
                    store.close();
                } catch (MessagingException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    //一封邮件的结构
    //大部分商业邮件都是HTML邮件,所以下载的邮件可以将body作为HTML文件查看,但只能加载出图片
    //因为传输协议加密内容都有都有==结尾,经过博主测试外面都有外包base64加密
    //有一些纯文本甚至可以直接由base64解码查看,所以一定不要让你的授权码外泄
    static void printMessage(MimeMessage msg) throws IOException, MessagingException {
        System.out.println("--------------------");
        System.out.println("Subject: " + MimeUtility.decodeText(msg.getSubject()));
        System.out.println("From: " + getFrom(msg));
        System.out.println("To: " + getTo(msg));
        System.out.println("Sent: " + msg.getSentDate().toString());
        System.out.println("Seen: " + msg.getFlags().contains(Flags.Flag.SEEN));
        System.out.println("Priority: " + getPriority(msg));
        System.out.println("Size: " + msg.getSize() / 1024 + "kb");
        System.out.println("Body: " + getBody(msg));
        System.out.println("--------------------");
        System.out.println();
    }

    static String getFrom(MimeMessage msg) throws IOException, MessagingException {
        Address[] froms = msg.getFrom();
        return addressToString(froms[0]);
    }

    static String getTo(MimeMessage msg) throws MessagingException, IOException {
        // 使用 msg.getAllRecipients() 获取所有收件人
        Address[] tos = msg.getRecipients(MimeMessage.RecipientType.TO);
        List<String> list = new ArrayList<>();
        for (Address to : tos) {
            list.add(addressToString(to));
        }
        return String.join(", ", list);
    }

    static String addressToString(Address addr) throws IOException {
        InternetAddress address = (InternetAddress) addr;
        String personal = address.getPersonal();
        return personal == null ? address.getAddress()
                : (MimeUtility.decodeText(personal) + " <" + address.getAddress() + ">");
    }

    static String getPriority(MimeMessage msg) throws MessagingException {
        String priority = "Normal";
        String[] headers = msg.getHeader("X-Priority");
        if (headers != null) {
            String header = headers[0];
            if ("1".equals(header) || "high".equalsIgnoreCase(header)) {
                priority = "High";
            } else if ("5".equals(header) || "low".equalsIgnoreCase(header)) {
                priority = "Low";
            }
        }
        return priority;
    }

    static String getBody(Part part) throws MessagingException, IOException {
        if (part.isMimeType("text/*")) {
            return part.getContent().toString();
        }
        if (part.isMimeType("multipart/*")) {
            Multipart multipart = (Multipart) part.getContent();
            for (int i = 0; i < multipart.getCount(); i++) {
                BodyPart bodyPart = multipart.getBodyPart(i);
                String body = getBody(bodyPart);
                if (!body.isEmpty()) {
                    return body;
                }
            }
        }
        return "";
    }
}

小结

使用POP3协议时,需要用Maven引入JavaMail依赖,并确定POP3服务器的域名/端口/是否使用SSL等,然后,调用相关API接收Email

大结

1.可以通过线程池实现批量发送邮件
2.发送邮件前要在xml中引入项目,你们需要我可以写个博客做个小结,毕竟有不少坑
3.喜欢就点个赞呗
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肖半仙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值