java email

java 邮件

电子邮件

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

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

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

SMTP

SMTP协议是基于TCP/IP的一个应用层协议,类似于HTTP,全称为 Simple Mail Transfer Protocol,译作简单邮件传输协议,它定义了邮件客户端软件与SMTP 服务器之间,以及 SMTP 服务器与 SMTP 服务器之间的通信规则。我们通过邮件客户端或程序发送邮件时就用到了该协议。
而 POP3 协议全称为 Post Office Protocol ,译作邮局协议,它定义了邮件客户端与 POP3服务器之间的通信规则。我们通过邮件客户端查看邮件时就用到了该协议。
IMAP(Internet Message Access Protocol)协议是对POP3协议的一种扩展,功能更强,作用类似。

传输协议

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发送邮件

条件

得到两个jar包:

  • mail.jar
  • activation.jar

概述

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

QQ邮箱中获取对应的权限

进入QQ邮箱–>邮箱设置–>账户,下滑找到POP3/IMAP/SMTP/Exchange/CardDav/CalDav服务,开启POP3/SMTP服务

常用类

MimeMessage

public class MimeMessage extends Message implements MimePart

  • 概述

这个类表示一个MIME样式的电子邮件消息。它实现了消息抽象类和MimePart接口。希望创建新的MIME样式消息的客户端将实例化一个空的MimeMessage对象,然后用适当的属性和内容填充它。实现MIME兼容后端存储的服务提供者可能想要继承MimeMessage并覆盖某些方法来提供特定的实现。

最简单的例子可能是一个提供者生成一个MIME样式的输入流,并将流的解析工作留给这个类。MimeMessage使用InternetHeaders类来解析和存储顶级的RFC 822消息头。mail.mime.address。strict session属性控制地址头的解析。默认情况下,对地址头进行严格解析。如果此属性设置为“false”,则不会进行严格解析,并且允许在真实消息中出现的许多非法地址。有关详细信息,请参阅InternetAddress类。

  • 常用方法

    MimeMessage(Session session) 默认构造函数。

    void addFrom(Address[] addresses) 将指定的地址添加到现有的“From”字段。

    void addRecipients(Message.RecipientType type, Address[] addresses)

    将给定的地址添加到指定的收件人类型

    void saveChanges ()
    更新此消息的适当头字段,使其与消息的内容一致。

    void setContent(Multipart mp)
    此方法将消息的内容设置为一个多部分对象。

    void setContent(Object o, String type)
    设置此消息内容的方便方法。

    void setContentID(String cid)
    设置此消息的“Content-ID”头字段。

    void setFileName(String filename)
    如果可能,设置与此部分相关联的文件名。

    void setFrom(Address address)

    设置RFC 822“From”报头字段

    void setRecipients(Message.RecipientType type, Address[] addresses)

    将指定的收件人类型设置为给定的地址。

    void setSentDate(Date d)

    设置RFC 822“Date”报头字段。这是消息创建者指示消息已完成并准备交付的日期。如果date参数为空,则现有的“date”字段将被删除。

    void setSubject(String subject) 设置标题字段subject。

    void setSubject(String subject, String charset)

    设置标题字段subject。方便的方法,将给定的字符串设置为这部分的内容,MIME类型为“text/plain”。

    void setText(String text, String charset)

    方便的方法,将给定的字符串设置为这部分的内容,MIME类型为“text/plain”并指定字符集。

    void setText(String subject, String charset)

    方便的方法,将给定的字符串设置为该部分的内容,主要MIME类型为“text”和指定的MIME子类型。

    voidwriteTo (OutputStream os)
    以rfc822格式流输出消息。

    voidwriteTo(OutputStream os, String[] ignoreList)

    输出以RFC 822格式流输出消息,不指定报头。

Address

public abstract class Address extends Object implements Serializable

  • 概述

这个抽象类对消息中的地址进行建模。子类提供特定的实现。子类通常是可序列化的,因此(例如)可以将搜索词中的Address对象与搜索词一起序列化。

  • 常用方法

abstract booleanequals(Object address)
相等操作符。

abstract StringgetType()
返回标识此地址类型的类型字符串。

abstract StringtoString()
返回此address对象的字符串表示形式。

Message.RecipientType

public static class Message.RecipientType extends Object implements Serializable

  • 概述

这个内部类定义了Message类允许的收件人类型。当前定义的类型是TO、CC和BCC。注意,这个类只有一个受保护的构造函数,因此限制新的接收者类型只能是这个类或子类。这有效地实现了允许的接收者类型的枚举。下面的代码示例展示了如何使用这个类从消息中获取“to”收件人。

  • 常用方法

    static Message.RecipientType BCC “密件抄送”(盲抄送)收件人。

    static Message.RecipientType CC 抄送(副本)收件人。

    static Message.RecipientType TO “收件人”(主要)收件人。

    protected String type 收件人的类型,通常是相应的Internet标准标头的名称

Multipart

public abstract class Multipart extends Object

  • 概述

Multipart是一个容纳多个身体部分的容器。Multipart提供了检索和设置其子部件的方法。

Multipart还充当大多数多部分datacontenthandler返回的内容对象的基类。例如,在源是“multipart/signed”数据源的DataHandler上调用getContent()可能会返回multipart的适当子类。

一些消息传递系统提供了多部分的不同子类型。例如,MIME指定了一组子类型,包括“alternative”,“mixed”,“related”,“parallel”,“signed”等等。
Multipart是一个抽象类。

  • 常用方法

void addBodyPart (BodyPart part)
将一个部件添加到多部件中。

void addBodyPart(BodyPart part, int index)
在位置索引处添加身体部分。

abstract void writeTo(OutputStream os)
将适当编码的字节流输出到给定的OutputStream。

protected void setMultipartDataSource(MultipartDataSource mp)

从给定的MultipartDataSource设置这个多部分对象。

MimeMultipart

public class MimeMultipart extends Multipart

  • 概述

MimeMultipart是从主要类型为“multipart”的MimePart中获得的(通过调用该部件的getContent()方法),或者可以由客户端在创建新的MimeMessage时创建它。

默认的多部分子类型是“mixed”。其他多部分子类型,如“alternative”、“related”等等,可以作为MimeMultipart的子类实现,并带有实现该类型多部分内容的附加语义的额外方法。其目的是让服务提供者、邮件JavaBean作者和邮件客户端编写许多这样的子类及其命令bean,并将它们安装到JavaBean激活框架中,这样任何JavaMail实现及其客户端都可以透明地查找和使用这些类。因此,MIME多部分处理程序的处理方式与任何其他类型处理程序一样,从而将提供多部分处理程序的过程与JavaMail API解耦。

如果没有这些额外的MimeMultipart子类,MIME多部分数据的所有子类型都将显示为MimeMultipart对象。应用程序可以使用MimeMultipart(String subtype)构造函数直接构造任何子类型的MIME多部分对象。例如,要创建一个“multipart/alternative”对象,请使用new MimeMultipart(“alternative”)。mail.mime.multipart。ignoremissingendboundary属性可以设置为false,以便在多部分数据没有以所需的结束边界线结束时引发MessagingException。如果此属性设置为true或未设置,则不认为缺少端边界是错误,并且最终主体部分在数据末尾结束。mail.mime.multipart。ignoremissingborderyparameter系统属性可以设置为false,如果MimeMultipart的内容类型不包含边界参数,则会引发MessagingException。如果此属性被设置为true或未设置,多部分解析代码将寻找一个看起来像边界线的行,并将其用作分隔部分的边界。mail.mime.multipart。ignoreexistingborderyparameter系统属性可以设置为true以导致忽略任何边界,而不是像mail.mime.multipart. ignoremissingborderyparameter那样在消息中搜索边界。通常,当写出不包含正文部分的MimeMultipart时,或尝试解析不包含正文部分的多部分消息时,会抛出MessagingException。MIME规范不允许没有主体部分的多部分内容。mail.mime.multipart。allowempty System属性可以设置为true以覆盖此行为。当写出这样一个MimeMultipart时,会包含一个空的部分。当读取这样的multipart时,将创建一个没有body part的MimeMultipart。

  • 常用方法

    void setSubType(String subtype)

    设置子类型。

BodyPart

public abstract class BodyPart extends Object implements Part

这个类为包含在多个部件中的部件建模。这是一个抽象类。子类提供了实际的实现。
BodyPart实现Part接口。因此,它包含一组属性和一个“内容”。

MimeBodyPart

public class MimeBodyPart extends BodyPart implements MimePart

  • 概述

这个类表示MIME主体部分。它实现BodyPart抽象类和MimePart接口。mimmebodyparts包含在MimeMultipart对象中。MimeBodyPart使用InternetHeaders类来解析和存储body部分的头。

RFC 822报头字段必须只包含US-ASCII字符。MIME允许非ASCII字符出现在某些标题的某些部分,通过编码这些字符。RFC 2047指定了这样做的规则。这个包中提供的MimeUtility类可以用来实现这一点。setHeader、addHeader和addHeaderLine方法的调用者负责强制指定头的MIME需求。此外,如果这些报头字段超过了传输的行长度限制(SMTP为1000字节),则在发送之前必须对它们进行折叠(包装)

  • 常用方法

voidsetContent(Multipart mp)
此方法将主体部分的内容设置为一个多部分对象。

voidsetContent(Object o, String type)
一种方便的设置主体部分内容的方法。

voidsetContentID(String cid)
设置正文部分的“Content-ID”报头字段。

voidsetDataHandler (DataHandler dh)
此方法提供了设置此主体部分内容的机制。

voidsetFileName(String filename)

如果可能,设置与正文部分相关联的文件名。

Authenticator

public abstract class Authenticator extends Object

  • 概述

Authenticator类表示一个知道如何获取网络连接身份验证的对象。通常,它会提示用户输入信息。应用程序通过创建子类来使用该类,并在创建该子类时向会话注册该子类的实例。当需要身份验证时,系统将调用子类上的一个方法(如getPasswordAuthentication)。子类的方法可以使用继承的许多方法(getRequestingXXX())查询所请求的身份验证,并为用户形成适当的消息。所有请求身份验证的方法都有一个失败的默认实现。

Transport

public abstract class Transport extends Service

  • 概述

对消息传输进行建模的抽象类。子类提供了实际的实现。
请注意,Transport扩展了Service类,它提供了许多通用的方法来命名传输、连接到传输和监听连接事件。

  • 常用方法

    abstract void sendMessage(Message msg, Address[] addresses) 将消息发送到指定的地址列表。

    protected boolean protocolConnect(String host, int port, String user, String password)throws MessagingException

    服务实现应该覆盖此方法,以执行实际的特定于协议的连接尝试。connect方法的默认实现会根据需要调用此方法。如果认证需要用户名或密码,但对应的参数为空,protocolConnect方法应该返回false;connect方法将在需要提供缺少的信息时提示用户。如果对提供的用户名或密码进行身份验证失败,此方法也可能返回false。或者,当身份验证失败时,此方法可能抛出AuthenticationFailedException。此异常可能包括一个字符串消息,其中包含有关失败的更多细节。protocolConnect方法应该抛出一个异常来报告与身份验证无关的失败,比如无效的主机名或端口号、身份验证过程中的连接丢失、服务器不可用等。

实例

 //创建一个配置文件并保存
        Properties properties = new Properties();
        properties.setProperty("mail.host", "smtp.qq.com"); //服务器
        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");
        properties.put("mail.smtp.ssl.socketFactory", sf);
        
        // 根据参数配置,创建会话对象(为了发送邮件准备的)
        Session session = Session.getDefaultInstance(properties, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication("2547333696@qq.com","lebvnsnlpkuhdifd");
            }
        });


        session.setDebug(true);

        MimeMessage message = new MimeMessage(session);     // 创建邮件对象

        Transport transport = session.getTransport();
        transport.connect("smtp.qq.com", "2547333696@qq.com", "lebvnsnlpkuhdifd");
        // 2. From: 发件人
        //    其中 InternetAddress 的三个参数分别为: 邮箱, 显示的昵称(只用于显示, 没有特别的要求), 昵称的字符集编码
        //    真正要发送时, 邮箱必须是真实有效的邮箱。
        message.setFrom(new InternetAddress("2547333696@qq.com"));

        // 3. To: 收件人
        message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress("2547333696@qq.com"));
        //    To: 增加收件人(可选)
        message.addRecipient(MimeMessage.RecipientType.TO, new InternetAddress("2547333696@qq.com"));
        //    Cc: 抄送(可选)
        message.setRecipient(MimeMessage.RecipientType.CC, new InternetAddress("2547333696@qq.com"));
        //    Bcc: 密送(可选)
        message.setRecipient(MimeMessage.RecipientType.BCC, new InternetAddress("2547333696@qq.com"));

        // 4. Subject: 邮件主题
        message.setSubject("TEST邮件主题", "UTF-8");

        // 5. Content: 邮件正文(可以使用html标签)
        message.setContent("TEST这是邮件正文。。。", "text/html;charset=UTF-8");

        // 6. 设置显示的发件时间
        message.setSentDate(new Date());

        // 7. 保存前面的设置
        message.saveChanges();

        //8. 发送邮件, 发到所有的收件地址, message.getAllRecipients() 获取到的是在创建邮件对象时添加的所有收件人, 抄送人, 密送人
        transport.sendMessage(message, message.getAllRecipients());

        transport.close();
//创建一个配置文件并保存
        Properties properties = new Properties();
        properties.setProperty("mail.host", "smtp.qq.com"); //服务器
        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");
        properties.put("mail.smtp.ssl.socketFactory", sf);

        Session session = Session.getDefaultInstance(properties, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication("2547333696@qq.com","lebvnsnlpkuhdifd");
            }
        });

        // 根据参数配置,创建会话对象(为了发送邮件准备的)
        session.setDebug(true);

        MimeMessage message = new MimeMessage(session);     // 创建邮件对象

        Transport transport = session.getTransport();
        transport.connect("smtp.qq.com", "2547333696@qq.com", "lebvnsnlpkuhdifd");
        // 2. From: 发件人
        //    其中 InternetAddress 的三个参数分别为: 邮箱, 显示的昵称(只用于显示, 没有特别的要求), 昵称的字符集编码
        //    真正要发送时, 邮箱必须是真实有效的邮箱。
        message.setFrom(new InternetAddress("2547333696@qq.com"));

        // 3. To: 收件人
        message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress("2547333696@qq.com"));
        //    To: 增加收件人(可选)
        message.addRecipient(MimeMessage.RecipientType.TO, new InternetAddress("2547333696@qq.com"));
        //    Cc: 抄送(可选)
        message.setRecipient(MimeMessage.RecipientType.CC, new InternetAddress("2547333696@qq.com"));
        //    Bcc: 密送(可选)
        message.setRecipient(MimeMessage.RecipientType.BCC, new InternetAddress("2547333696@qq.com"));

        // 4. Subject: 邮件主题
        message.setSubject("TEST邮件主题", "UTF-8");

        //        MimeBodyPart
//        javax.mail.internet.MimeBodyPart类 表示的是一个MIME消息,它和MimeMessage类一样都是从Part接口继承过来。
//        MimeMultipart
//        javax.mail.internet.MimeMultipart是抽象类 Multipart的实现子类,它用来组合多个MIME消息。一个MimeMultipart对象可以包含多个代表MIME消息的MimeBodyPart对象

        //附件图片出处理
        MimeBodyPart image = new MimeBodyPart();
        image.setDataHandler(new DataHandler(new FileDataSource(new File("C:\\Users\\ASUS\\Desktop\\123.jpg"))));
        image.setContentID("123.jpg");


        MimeBodyPart text = new MimeBodyPart();
        text.setContent("这封邮件包含文本与<img src='cid:123.jpg' />邮件","text/html;charset=UTF-8");

        MimeMultipart body = new MimeMultipart();
        body.addBodyPart(image);
        body.addBodyPart(text);
        body.setSubType("mixed");

        message.setContent(body);

        // 6. 设置显示的发件时间
        message.setSentDate(new Date());

        // 7. 保存前面的设置
        message.saveChanges();

        //8. 发送邮件, 发到所有的收件地址, message.getAllRecipients() 获取到的是在创建邮件对象时添加的所有收件人, 抄送人, 密送人
        transport.sendMessage(message, message.getAllRecipients());

        transport.close();
//创建一个配置文件并保存
        Properties properties = new Properties();
        properties.setProperty("mail.host", "smtp.qq.com"); //服务器
        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");
        properties.put("mail.smtp.ssl.socketFactory", sf);

        //验证
        Session session = Session.getDefaultInstance(properties, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication("2547333696@qq.com","lebvnsnlpkuhdifd");
            }
        });

        // 根据参数配置,创建会话对象(为了发送邮件准备的)
        session.setDebug(true);

        MimeMessage message = new MimeMessage(session);     // 创建邮件对象

        Transport transport = session.getTransport();
        transport.connect("smtp.qq.com", "2547333696@qq.com", "lebvnsnlpkuhdifd");
        // 2. From: 发件人
        //    其中 InternetAddress 的三个参数分别为: 邮箱, 显示的昵称(只用于显示, 没有特别的要求), 昵称的字符集编码
        //    真正要发送时, 邮箱必须是真实有效的邮箱。
        message.setFrom(new InternetAddress("2547333696@qq.com"));

        // 3. To: 收件人
        message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress("2491832500@qq.com"));
        //    To: 增加收件人(可选)
//        message.addRecipient(MimeMessage.RecipientType.TO, new InternetAddress("2547333696@qq.com"));
        //    Cc: 抄送(可选)
        message.setRecipient(MimeMessage.RecipientType.CC, new InternetAddress("2547333696@qq.com"));
        //    Bcc: 密送(可选)
        message.setRecipient(MimeMessage.RecipientType.BCC, new InternetAddress("2547333696@qq.com"));

        // 4. Subject: 邮件主题
        message.setSubject("TEST邮件主题", "UTF-8");


        //        MimeBodyPart
//        javax.mail.internet.MimeBodyPart类 表示的是一个MIME消息,它和MimeMessage类一样都是从Part接口继承过来。
//        MimeMultipart
//        javax.mail.internet.MimeMultipart是抽象类 Multipart的实现子类,它用来组合多个MIME消息。一个MimeMultipart对象可以包含多个代表MIME消息的MimeBodyPart对象

        //附件图片出处理
        MimeBodyPart image = new MimeBodyPart();
        image.setDataHandler(new DataHandler(new FileDataSource(new File("C:\\Users\\ASUS\\Desktop\\123.jpg"))));
        image.setContentID("123.jpg");

        MimeBodyPart text = new MimeBodyPart();
        text.setContent("这封邮件包含文本与<img src='cid:123.jpg' />邮件","text/html;charset=UTF-8");

        //附件
        MimeBodyPart file01 = new MimeBodyPart();
        file01.setDataHandler(new DataHandler(new FileDataSource(new File("C:\\Users\\ASUS\\Desktop\\123.txt"))));
        file01.setFileName("123.txt");

        MimeBodyPart file02 = new MimeBodyPart();
        file02.setDataHandler(new DataHandler(new FileDataSource(new File("C:\\Users\\ASUS\\Desktop\\456.txt"))));
        file02.setFileName("1456.txt");


        //封装文本与图片
        MimeMultipart body = new MimeMultipart();
        body.addBodyPart(image);
        body.addBodyPart(text);
        body.setSubType("mixed");


        //定义文本与图片为主体
        MimeBodyPart body02 = new MimeBodyPart();
        body02.setContent(body);

        //定义数据
        MimeMultipart data = new MimeMultipart();
        data.addBodyPart(body02);
        data.addBodyPart(file01);
        data.addBodyPart(file02);
        data.setSubType("mixed");


        message.setContent(data);

        // 6. 设置显示的发件时间
        message.setSentDate(new Date());

        // 7. 保存前面的设置
        message.saveChanges();

        //8. 发送邮件, 发到所有的收件地址, message.getAllRecipients() 获取到的是在创建邮件对象时添加的所有收件人, 抄送人, 密送人
        transport.sendMessage(message, message.getAllRecipients());

        transport.close();
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值