Java发送邮件详解

目录

一、关于电子邮件

电子邮件

传输协议

SMTP协议

POP3协议

邮件收发原理

二、发送纯文本邮件

二、发送带图片和附件的邮件


一、关于电子邮件

电子邮件

要在网络上实现邮件功能,必须要有专门的邮件服务器。

这些邮件服务器类似于现实生活中的邮局,它主要负责接收用户投递过来的邮件,并把邮件投递到邮件接收者的电子邮箱中。

SMTP服务器地址:一般是 smtp.xxx.com,比如163邮箱是smtp.163.com,qq邮箱是smtp.qq.com。

使用Java发送邮件,还需要设置使用账号开启相关服务,拿到授权码:

传输协议

SMTP协议

发送邮件:

我们通常把处理用户smtp请求(邮件发送请求)的服务器称之为SMTP服务器(邮件发送服务器)。

POP3协议

接收邮件:

我们通常把处理用户pop3请求(邮件接收请求)的服务器称之为POP3服务器(邮件接收服务器)。

邮件收发原理

1、首先通过smtp协议连接到Smtp服务器,然后发送一封邮件给网易的邮件服务器
2、网易分析发现需要去QQ的邮件服务器,通过smtp协议将邮件转投给QQ的Smtp服务器
3、QQ将接收到的邮件存储在545646733@qq.com这个邮件账号的空间中
4、再通过Pop3协议连接到Pop3服务器收取邮件
5、从545646733@qq.com这个邮件账号的空间中取出邮件
6、Pop3服务器将取出来的邮件送出去

二、发送纯文本邮件

使用Java发送邮件,首先需要引入相关的依赖:

<dependency>
     <groupId>javax.mail</groupId>
     <artifactId>mail</artifactId>
     <version>1.4.4</version>
</dependency>

JavaMail 是sun公司(现以被甲骨文收购)为方便Java开发人员在应用程序中实现邮件发送和接收功能而提供的一套标准开发包,它支持一些常用的邮件协议,如前面所讲的SMTP,POP3,IMAP,还有MIME等。我们在使用JavaMail API 编写邮件时,无须考虑邮件的底层实现细节,只要调用JavaMail 开发包中相应的API类就可以了。
Java发送邮件三步骤:

1、创建包含连接邮件服务器授权信息的Session对象

(1)编写抽象类Authenticator的实现子类,在子类中覆盖父类的getPasswordAuthentication方法,并返回封装用户名和密码的PasswordAuthentication对象;

(2) 调用Session.getInstance(Properties, Authenticator)方法获得Session类的实例对象,并把Authenticator对象注册到Session对象中。

2、创建代表邮件内容的Message对象

使用Session对象创建代表邮件消息内容的Message对象

3、通过Transport,发送Message

方式一:调用Transport.send静态方法发送Message对象中的邮件消息内容。send方法将从Message对象中获得Session对象的引用,然后将调用Session对象中注册的Authenticator对象从中获取认证信息后传递给邮件服务器。

方式二:使用Transport的connect方法连接邮件服务器,然后使用sendMessage发送发送邮件;最后调用close方法关闭邮件服务器的连接。(不推荐,麻烦)

代码示例:

public class SendEmail {
    public static void main(String[] args) throws MessagingException, GeneralSecurityException {

        Properties props = new Properties();
        // 设置邮件服务器 QQ:smtp.qq.com    163:smtp.163.com
        props.setProperty("mail.smtp.host", "smtp.qq.com");
        // 设置是否需要验证用户名
        props.setProperty("mail.smtp.auth", "true");

        // 如果是QQ邮箱,还要设置SSL加密,加上以下代码即可
        MailSSLSocketFactory sf = new MailSSLSocketFactory();
        sf.setTrustAllHosts(true);
        props.put("mail.smtp.ssl.enable", "true");
        props.put("mail.smtp.ssl.socketFactory", sf);

        /**
         * 发送邮件三步骤
         */
        
        // 1、创建定义整个应用程序所需的环境信息的Session 对象
        Session session = Session.getInstance(props, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                // 发件人邮件用户名、授权码
                return new PasswordAuthentication("xxx@qq.com", "xxx");
            }
        });
        // 开启Session的debug模式,这样就可以查看到程序发送Email的运行状态
        session.setDebug(true);

        // 2、创建邮件对象
        MimeMessage message = new MimeMessage(session);
        // 发件人
        message.setFrom(new InternetAddress("xxx@qq.com"));
        // 指定收件人
        message.setRecipients(Message.RecipientType.TO, "xxx@126.com");
        // 指定抄送人
        message.setRecipients(Message.RecipientType.CC, "xxx@qq.com");
        // 设置邮件主题
        message.setSubject("Announcement");
        // 设置邮件内容
        message.setText("let's go party!");
        // 设置发送时间
        message.setSentDate(new Date());

        // 3、发送邮件,调用Transport.send静态方法发送Message对象中的邮件消息内容
        Transport.send(message);
    }
}

二、发送带图片和附件的邮件

先认识两个类一个名词:

MIME(多用途互联网邮件扩展类型)

MiniMultipart类

MiniMultipart类是一个容器类,包含MimeBodyPart类型的对象,Javamail邮件Multipart支持同时发text和html混合消息。

常见的multipart类型有三种:

multipart/mixed:附件。

multipart/related:内嵌资源。

multipart/alternative:纯文本与超文本共存。

如果在邮件中要添加附件,必须定义multipart/mixed段;如果存在内嵌资源,至少要定义multipart/related段;如果纯文本与超文本共存,至少要定义multipart/alternative段。什么是“至少”?举个例子说,如果只有纯文本与超文本正文,那么在邮件头中将类型扩大化,定义为multipart/related,甚至multipart/mixed,都是允许的。

MimeMultipart是Multipart的实现类,默认类别是mixed。其他multipart子类型如:related和alternative可以通过new MimeMultipart(“alternative”)来实现

代码示例:

public class SendEmail {
    public static void main(String[] args) throws MessagingException, GeneralSecurityException {
        
        Properties props = new Properties();
        // 设置邮件服务器 QQ:smtp.qq.com    163:smtp.163.com
        props.setProperty("mail.smtp.host", "smtp.qq.com");
        // 设置是否需要验证用户名
        props.setProperty("mail.smtp.auth", "true");

        // 如果是QQ邮箱,还要设置SSL加密,加上以下代码即可
        MailSSLSocketFactory sf = new MailSSLSocketFactory();
        sf.setTrustAllHosts(true);
        props.put("mail.smtp.ssl.enable", "true");
        props.put("mail.smtp.ssl.socketFactory", sf);

        /**
         * 发送邮件三步骤
         */

        // 1、创建定义整个应用程序所需的环境信息的Session 对象
        Session session = Session.getInstance(props, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                // 发件人邮件用户名、授权码
                return new PasswordAuthentication("xxx@qq.com", "xxx");
            }
        });
        // 开启Session的debug模式,这样就可以查看到程序发送Email的运行状态
        session.setDebug(true);

        // 2、创建邮件对象
        MimeMessage message = new MimeMessage(session);
        // 发件人
        message.setFrom(new InternetAddress("xxx@qq.com"));
        // 指定收件人
        message.setRecipients(Message.RecipientType.TO, "xxx@126.com");
        // 指定抄送人
        message.setRecipients(Message.RecipientType.CC, "xxx@qq.com");
        // 设置邮件主题
        message.setSubject("带图片的信息");

        // 图片
        MimeBodyPart image = new MimeBodyPart();
        DataHandler dataHandler = new DataHandler(new FileDataSource("D:\\demofiles\\gougou.jpg"));
        image.setDataHandler(dataHandler);
        image.setContentID("gougou");// 图片设置ID
        // 文本
        MimeBodyPart text = new MimeBodyPart();
        text.setContent("这是一封邮件正文带图片<img src='cid:gougou' width='200' height='100'>的邮件", "text/html;charset=UTF-8");
        // 附件一
        MimeBodyPart appendix1 = new MimeBodyPart();// 把前一张图片覆盖掉了
        DataHandler appendixHandler1 = new DataHandler(new FileDataSource("D:\\demofiles\\lang.jpg"));
        appendix1.setDataHandler(appendixHandler1);
        appendix1.setFileName("lang.jpg");// 为附件设置名字,不能和内嵌文件重名,否则<img/>会解析出错
        // 附件二
        MimeBodyPart appendix2 = new MimeBodyPart();
        DataHandler appendixHandler2 = new DataHandler(new FileDataSource("D:\\demofiles\\flowers.jpg"));
        appendix2.setDataHandler(appendixHandler2);
        appendix2.setFileName("lang.jpg");// 附件和附件的名字可以一样,邮件会自动标号区别

        // 描述数据关系:文本+图片,捆绑成一个related
        MimeMultipart related = new MimeMultipart("related");
        related.addBodyPart(text);
        related.addBodyPart(image);
        // 将拼装好的正文内容捆绑成一个主体
        MimeBodyPart contentText =  new MimeBodyPart();
        contentText.setContent(related);
        // 描述数据关系: 附件+(文本+图片)
        MimeMultipart allFile =new MimeMultipart("mixed");
        allFile.addBodyPart(appendix1); // 附件一
        allFile.addBodyPart(appendix2); // 附件二
        allFile.addBodyPart(contentText);// 正文内容
        // allFile.addBodyPart(image); // 不能再设置image为附件,无效
        // allFile.addBodyPart(appendix2); // 附件同文件可以重复

        // 封装Message消息,保存修改
        message.setContent(allFile);
        message.saveChanges();
        // 设置发送时间
        message.setSentDate(new Date());

        // 3、发送邮件,调用Transport.send静态方法发送Message对象中的邮件消息内容
        Transport.send(message);
    }
}

代码中,<img/>标签用到了cid,那什么是cid呢?

一封邮件由邮件头(Headers)和邮件体组成的,邮件头中包括了各种属性,其中就有cid,即Content-Id,下图是Java邮件开发详解中对Content-id的解释(张孝祥版PDF)

这个cid跟这封邮件的内嵌资源一一对应,这个cid主要用来替换你下载到本地的资源文件比如gif表情,然后将src中的路径换成本地路径才能正常显示,这个没有附件容易理解,其实可以这样理解,他也是附件,就是你要先下载到本地,替换完之后才能正常的展示到用户面前,多了个下载的过程,而附件可以直接展示,点击某个附件再调用下载的过程。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
当需要在邮件正文中嵌入图片时,可以使用HTML格式的邮件,并在HTML中嵌入图片的URL。下面是使用JavaMail发送包含图片的HTML格式邮件的详细步骤: 1. 导入JavaMail和javax.activation库。 2. 创建一个MimeMessage对象。 3. 设置邮件的基本信息,包括发件人、收件人、主题等。 4. 创建一个Multipart对象,用于组合邮件正文和图片。 5. 创建一个HTML格式的邮件正文。 6. 创建一个MimeBodyPart对象,用于包装图片。 7. 将图片附件添加到MimeBodyPart对象中。 8. 将MimeBodyPart对象添加到Multipart对象中。 9. 将Multipart对象设置为邮件内容。 10. 发送邮件。 下面是一份示例代码,可以参考: ```java import javax.activation.DataHandler; import javax.activation.DataSource; import javax.activation.FileDataSource; import javax.mail.*; import javax.mail.internet.*; import java.util.Properties; public class SendMailWithImage { public static void main(String[] args) { // 发件人电子邮箱 String from = "from@example.com"; // 收件人电子邮箱 String to = "to@example.com"; // 指定发送邮件的主机为 smtp.qq.com String host = "smtp.qq.com"; //QQ 邮件服务器 // 获取系统属性 Properties properties = System.getProperties(); // 设置邮件服务器 properties.setProperty("mail.smtp.host", host); properties.put("mail.smtp.auth", "true"); // 获取默认session对象 Session session = Session.getDefaultInstance(properties, new Authenticator(){ public PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication("你的QQ账号", "你的QQ邮箱授权码"); //发件人邮件用户名、密码 } }); try{ // 创建默认的 MimeMessage 对象 MimeMessage message = new MimeMessage(session); // Set From: 头部头字段 message.setFrom(new InternetAddress(from)); // Set To: 头部头字段 message.addRecipient(Message.RecipientType.TO, new InternetAddress(to)); // Set Subject: 头部头字段 message.setSubject("包含图片的邮件"); // 创建消息部分 BodyPart messageBodyPart = new MimeBodyPart(); // 消息 String messageText = "<h1>这是一封包含图片的HTML格式邮件!</h1><br/><img src=\"cid:image\">"; messageBodyPart.setContent(messageText, "text/html"); // 创建多重消息 Multipart multipart = new MimeMultipart(); // 设置文本消息部分 multipart.addBodyPart(messageBodyPart); // 附件部分 messageBodyPart = new MimeBodyPart(); String filename = "image.png"; DataSource source = new FileDataSource(filename); messageBodyPart.setDataHandler(new DataHandler(source)); messageBodyPart.setHeader("Content-ID", "<image>"); multipart.addBodyPart(messageBodyPart); // 发送合成消息 message.setContent(multipart); // 发送消息 Transport.send(message); System.out.println("邮件发送成功!"); }catch (MessagingException mex) { mex.printStackTrace(); } } } ``` 其中,需要替换的部分有: - `from@example.com` 为发件人邮箱地址。 - `to@example.com` 为收件人邮箱地址。 - `smtp.qq.com` 为发件人邮箱SMTP服务器地址,可以根据实际情况进行修改。 - `你的QQ账号` 和 `你的QQ邮箱授权码` 分别为发件人邮箱的账号和授权码,需要替换为实际的内容。 - `image.png` 为要添加的图片文件名,需要替换为实际的图片文件名。 运行程序后,将会发送一封包含图片的HTML格式邮件

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

swadian2008

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

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

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

打赏作者

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

抵扣说明:

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

余额充值