用 setSubject() 方法设置 subject(主题):
message.setSubject(“First”);
下面的代码演示了创建一个简单邮件信息的过程:
Message msg = new MimeMessage(session);
msg.setSubject(“Test Title”);
msg.setText(“How are you!”);
msg.setSentDate(new Date());
Address****:地址****
一旦您创建了 Session 和 Message,并将内容填入消息后,就可以用 Address 确定信件地址了。和 Message 一样,Address 也是个抽象类。您用的是 javax.mail.internet.InternetAddress 类。
若创建的地址只包含电子邮件地址,只要传递电子邮件地址到构造器就行了。
Address address = new InternetAddress(“president@whitehouse.gov”);
若希望名字紧挨着电子邮件显示,也可以把它传递给构造器:
Address address = new InternetAddress(“president@whitehouse.gov”, “George Bush”);
需要为消息的 from 域和 to 域创建地址对象。除非邮件服务器阻止,没什么能阻止你发送一段看上去是来自任何人的消息。
一旦创建了 address(地址),将它们与消息连接的方法有两种。如果要识别发件人,您可以用 setFrom() 和 setReplyTo() 方法。
message.setFrom(address)
需要消息显示多个 from 地址,可以使用 addFrom() 方法:
Address address[] = …;
message.addFrom(address);
若要识别消息 recipient(收件人),您可以使用 addRecipient() 方法。除 address(地址)外,这一方法还请求一个 Message.RecipientType。
message.addRecipient(type, address)
三种预定义的地址类型是:
-
Message.RecipientType.TO:发送原始的
-
Message.RecipientType.CC:复写本,副本
-
Message.RecipientType.BCC:密件抄送,简写为Bcc,电子邮件用语,将邮 件转发多人,但收件人看不到此邮件转发给的其他人信息
如果消息是发给副总统的,同时发送一个副本(carbon copy)给总统夫人,以下做法比较恰当:
Address toAddress = new InternetAddress(“vice.president@whitehouse.gov”);
Address ccAddress = new InternetAddress(“first.lady@whitehouse.gov”);
message.addRecipient(Message.RecipientType.TO, toAddress);
message.addRecipient(Message.RecipientType.CC, ccAddress);
Java MailAPI 没有提供电子邮件地址有效性核查机制。虽然通过编程,自己能够扫描有效字符(如 RFC 822 中定义的)或验证邮件交换(mail exchange,MX)记录,但这些功能不属于 Java MailAPI。
Authenticator****:认证者****
与 java.net 类一样, Java MailAPI 也可以利用 Authenticator 通过用户名和密码访问受保护的资源。对于 Java MailAPI 来说,这些资源就是邮件服务器。 Java MailAuthenticator 在 javax.mail 包中,而且它和 java.net 中同名的类 Authenticator 不同。两者并不共享同一个 Authenticator,因为 Java MailAPI 用于 Java 1.1,它没有 java.net 类别。
要使用 Authenticator,先创建一个抽象类的子类,并从 getPasswordAuthentication() 方法中返回 PasswordAuthentication 实例。创建完成后,您必需向 session 注册 Authenticator。然后,在需要认证的时候,就会通知 Authenticator。您可以弹出窗口,也可以从配置文件中(虽然没有加密是不安全的)读取用户名和密码,将它们作为 PasswordAuthentication 对象返回给调用程序。
Properties props = new Properties();
// fill props with any information
Authenticator auth = new MyAuthenticator();
Session session = Session.getDefaultInstance(props, auth);
发送消息:
发送电子邮件消息这一过程包括获取一个会话,创建并填充一则消息,然后发送。得到 Session 时,经由设置传递的 Properties 对象中的 mail.smtp.host 属性,可以指定您的 SMTP 服务器:
String host = …;
String from = …;
String to = …;
// Get system properties
Properties props = System.getProperties();
// Setup mail server
props.put(“mail.smtp.host”, host);
// Get session
Session session = Session.getDefaultInstance(props, null);
// Define message
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
message.addRecipient(Message.RecipientType.TO,
new InternetAddress(to));
message.setSubject(“Hello JavaMail”);
message.setText(“Welcome to JavaMail”);
// Send message
Transport.send(message);
您应该将代码放在一个 try-catch 程序块中,这样创建和发送消息时就能够抛出异常。
消息的提取:
为读邮件,您获取一个会话,获取并连接一个用于邮箱的适宜的存储(store),打开适宜的文件夹,然后获取您的消息。同样,切记完成后关闭连接。
String host = …;
String username = …;
String password = …;
// Create empty properties
Properties props = new Properties();
// Get session
Session session = Session.getDefaultInstance(props, null);
// Get the store
Store store = session.getStore(“pop3”);
store.connect(host, username, password);
// Get folder
Folder folder = store.getFolder(“INBOX”);
folder.open(Folder.READ_ONLY);
// Get directory
Message message[] = folder.getMessages();
for (int i=0, n=message.length; i<n; i++) {
System.out.println(i + ": " + message[i].getFrom()[0]
- “\t” + message[i].getSubject());
}
// Close connection
folder.close(false);
store.close();
对每条消息做些什么由您决定。上面的代码块只是显示这些消息的发件人和主题。技术上讲,from 地址列表可能为空,而 getFrom()[0] 调用会抛出一个异常。
要显示全部信息,您可以在用户看完 from 和 subject 域之后给出提示,如用户有需要,就调用消息的 writeTo() 方法来实现。
BufferedReader reader = new BufferedReader (
new InputStreamReader(System.in));
// Get directory
Message message[] = folder.getMessages();
for (int i=0, n=message.length; i<n; i++) {
System.out.println(i + ": " + message[i].getFrom()[0]
- “\t” + message[i].getSubject());
System.out.println("Do you want to read message? " +
“[YES to read/QUIT to end]”);
String line = reader.readLine();
if (“YES”.equals(line)) {
message[i].writeTo(System.out);
} else if (“QUIT”.equals(line)) {
break;
}
}
消息和标识的删除:
消息的删除涉及使用与消息相关的 Flags(标志)。不同 flag 对应不同的状态,有些由系统定义而有些则由用户定义。下面列出在内部类 Flags.Flag 中预定义的标志:
-
Flags.Flag.ANSWERED
-
Flags.Flag.DELETED
-
Flags.Flag.DRAFT
-
Flags.Flag.FLAGGED
-
Flags.Flag.RECENT
-
Flags.Flag.SEEN
-
Flags.Flag.USER
仅仅因为存在一个标志,并不意味着所有邮件服务器或供应商都支持这个标志。例如,除了删除消息标志外,POP 协议不再支持其它任何标志。检查是否存在新邮件,这不是个 POP 任务,而是内建于邮件客户机的任务。为找出哪些标志能被支持,可以用 getPermanentFlags() 向 folder 提出要求。
要删除消息,您可以设置消息的 DELETED flag:
message.setFlag(Flags.Flag.DELETED, true);
首先,请以 READ_WRITE 模式打开 folder:
folder.open(Folder.READ_WRITE);
然后,当所有消息的处理完成后,关闭 folder,并传递一个 true 值,从而擦除(expunge)有 delete 标志的消息。
folder.close(true);
一个 Folder 的 expunge() 方法可以用来删除消息。但 Sun 的 POP3 供应商不支持。其它供应商有的或许能够实现这一功能,而有的则不能。IMAP 供应商极有可能实现此功能。因为 POP 只支持单个对邮箱的访问,对 Sun 的供应商来说,您必需关闭 folder 以删除消息。
要取消标志,只要传递 false 给 setFlag() 方法就行了。想知道是否设置过标志,可以用 isSet() 检查。
亲自认证:
您已经知道 — 如果需要可以用一个 Authenticator 提示用户输入用户名和密码,而不是将用户名和密码作为字符串传递。在这里您会明确了解怎样更充分的使用认证。
不用主机、用户名和密码与 Store 相连接,而是设置 Properties 来拥有主机,然后告诉 Session 自定义的 Authenticator 实例,如下所示:
// Setup properties
Properties props = System.getProperties();
props.put(“mail.pop3.host”, host);
// Setup authentication, get session
Authenticator auth = new PopupAuthenticator();
Session session = Session.getDefaultInstance(props, auth);
// Get the store
Store store = session.getStore(“pop3”);
store.connect();
然后,您创建一个 Authenticator 子类并从 getPasswordAuthentication() 方法中返回 PasswordAuthentication 对象。下面就是这样一种实现,其中用户名和密码仅占用一个域。(这不是一个 Swing 工程教程;只要将两部分输入同一个域,用逗号分隔就行。)
import javax.mail.*;
import javax.swing.*;
import java.util.*;
public class PopupAuthenticator extends Authenticator {
public PasswordAuthentication getPasswordAuthentication() {
String username, password;
String result = JOptionPane.showInputDialog(
“Enter ‘username,password’”);
StringTokenizer st = new StringTokenizer(result, “,”);
username = st.nextToken();
password = st.nextToken();
return new PasswordAuthentication(username, password);
}
}
因为 PopupAuthenticator 涉及到 Swing,它会启动 AWT 的事件处理线程。这一点基本上要求您在代码中添加一个对 System.exit() 的调用来终止程序。
消息的回复:
Message 类引入一个 reply() 方法来配置一个新 Message,包括正确的 recipient(收件人)和添加“Re”(如果没有就添加)的正确的 subject。这样做并没有为消息添加新内容,仅仅将 from 或 reply-to(被回复人) 头复制给新的收件人。这种方法用一个 boolean 参数指定消息只回复给发件人(false)或回复给全体(true)。
MimeMessage reply = (MimeMessage)message.reply(false);
reply.setFrom(new InternetAddress(“president@whitehouse.gov”));
reply.setText(“Thanks”);
Transport.send(reply);
在发送消息时要配置 reply to(被回复人) 地址,可以用 setReplyTo() 方法。
消息的转发:
转发消息有一点棘手。没有单独的方法可以调用,您通过对组成消息各部分的处理来组织要转发的消息。
一条邮件消息可以由多个部分组成。在处理 MIME 消息时,消息中每部分都是 BodyPart,再特殊些,是 MimeBodyPart。不同的 body part(信体部件或正文部件)结合成一个容器,名为 Multipart,再特殊些,就是 MimeMultipart。要转发一条消息,您为自己的消息正文创建一个部件,要转发的消息作为另一部件。并且将两个部件结合成一个 multipart(多部件)。然后您将这个 multipart 添加到一则已写好恰当地址的消息中,并发送。
本质上就是如此。要将一条消息内容复制到另一条,只要复制 DataHandler (JavaBeans Activation Framework 中的类)就行了。
// Create the message to forward
Message forward = new MimeMessage(session);
// Fill in header
forward.setSubject("Fwd: " + message.getSubject());
forward.setFrom(new InternetAddress(from));
forward.addRecipient(Message.RecipientType.TO,
new InternetAddress(to));
// Create your new message part
BodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setText(
“Here you go with the original message:\n\n”);
// Create a multi-part to combine the parts
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(messageBodyPart);
// Create and fill part for the forwarded content
messageBodyPart = new MimeBodyPart();
messageBodyPart.setDataHandler(message.getDataHandler());
// Add part to multi part
multipart.addBodyPart(messageBodyPart);
// Associate multi-part with message
forward.setContent(multipart);
// Send message
Transport.send(forward);
附件的处理:
附件是邮件消息的相关资源,如通常不包含在消息正文里文本文件、电子表格或图像等。常见的邮件程序,如 Eudora 和 pine 之类,可以用 Java MailAPI 将资源 attach(附加) 到您的消息上,就可以在收到消息时得到。
附件的发送:
发送附件非常像转发消息。您建立各部分以组成完整消息。完成第一部件,即消息正文后,您添加其它部件,其中每个 DataHandler 都代表附件,而不是转发消息情况下的共享处理程序。如果从文件中读附件,附件的数据源是 FileDataSource。而如果从 URL 中读时,附件的数据源是 URLDataSource。一旦存在 DataSource,只要先把它传递给 DataHandler 构造器,最后再用 setDataHandler() 把它附加到 BodyPart。假定您要保留附件的原始文件名,最终要做的是用 BodyPart 的 setFileName() 方法设置与附件相关的文件名。如下所示:
// Define message
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
message.addRecipient(Message.RecipientType.TO,
new InternetAddress(to));
message.setSubject(“Hello Java MailAttachment”);
// Create the message part
BodyPart messageBodyPart = new MimeBodyPart();
// Fill the message
messageBodyPart.setText(“Pardon Ideas”);
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(messageBodyPart);
// Part two is attachment
messageBodyPart = new MimeBodyPart();
DataSource source = new FileDataSource(filename);
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName(filename);
multipart.addBodyPart(messageBodyPart);
// Put parts in message
message.setContent(multipart);
// Send the message
Transport.send(message);
就消息引入附件时,若程序是个 servlet (小服务程序),除告知消息发送到何处外,还必需上载附件。可以将 multipart/form-data 表单编码类型(form encoding type)用于每个上载文件的处理。
method=post action=“/myservlet”>
注意:消息大小由 SMTP 服务器而不是 Java MailAPI 来限制。如果您碰到问题,可以考虑用设置 ms 和 mx 参数的方法增大 Java 堆大小。
附件的获取:
从消息中获取附件比发送它们棘手些,因为 MIME 没有简单的关于附件的概念。当消息包含附件时,消息的内容是个 Multipart 对象。接着,您需要处理每个 Part,获取主要内容和附件。标有从 part.getDisposition() 获得的 Part.ATTACHMENT 配置(disposition)的部件(Part)无疑就是附件。但是,没有配置(以及一个非文本 MIME 类型)和带Part.INLINE 配置的部件也可能是附件。当配置要么是 Part.ATTACHMENT,要么是 Part.INLINE 时,这个消息部件的内容就能被保存。只要用 getFileName() 和 getInputStream() 就能分别得到原始文件名和输入流。
Multipart mp = (Multipart)message.getContent();
for (int i=0, n=multipart.getCount(); i<n; i++) {
Part part = multipart.getBodyPart(i));
String disposition = part.getDisposition();
if ((disposition != null) &&
((disposition.equals(Part.ATTACHMENT) ||
(disposition.equals(Part.INLINE))) {
saveFile(part.getFileName(), part.getInputStream());
}
}
saveFile() 方法仅依据文件名创建了一个 File,它从输入流中将字节读出,然后写入到文件中。万一文件已经存在,就在文件名后添加一个数字作为新文件名,如果这个文件名仍存在,则继续添,直到找不到这样的文件名为止。
// from saveFile()
File file = new File(filename);
for (int i=0; file.exists(); i++) {
file = new File(filename+i);
}
上面的代码涵盖了最简单的情况 — 消息中各部件恰当的标记了。要涵盖所有情况,还要在配置为空时进行处理,并且获取部件的 MIME 类型来进行相应处理。
if (disposition == null) {
// Check if plain
MimeBodyPart mbp = (MimeBodyPart)part;
if (mbp.isMimeType(“text/plain”)) {
// Handle plain
} else {
// Special non-attachment cases here of image/gif, text/html, …
}
…
}
对 HTML 消息的处理
发送基于 HTML 文件格式消息的工作量比发送纯文本消息多,虽然不一定非要这些多余的工作量。如何选择完全取决于给定的请求。
HTML 消息的发送:
若您所要做的全部事情是发送一份 HTML 文件的等价物作为消息,但让邮件阅读者为不能提取任何内嵌图像或相关片段而担心的话,可以使用 Message 的 setContent() 方法,把内容当作一个 String 传入,并将内容类型设置成 text/html。
String htmlText = “
Hello
” +“<img src=“http://www.jguru.com/images/logo.gif”>”;
message.setContent(htmlText, “text/html”));
在接收端,如果您用 Java MailAPI 提取消息,API 中没有内建的显示 HTML 消息的东西。 Java MailAPI 只把它看成一串字节流。要显示 HTML 文件格式的消息,您必需使用 Swing JEditorPane 或其它第三方 HTML 格式查看器组件。
if (message.getContentType().equals(“text/html”)) {
String content = (String)message.getContent();
JFrame frame = new JFrame();
JEditorPane text = new JEditorPane(“text/html”, content);
text.setEditable(false);
JScrollPane pane = new JScrollPane(text);
frame.getContentPane().add(pane);
frame.setSize(300, 300);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.show();
}
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
xt = “
Hello
” +“<img src=“http://www.jguru.com/images/logo.gif”>”;
message.setContent(htmlText, “text/html”));
在接收端,如果您用 Java MailAPI 提取消息,API 中没有内建的显示 HTML 消息的东西。 Java MailAPI 只把它看成一串字节流。要显示 HTML 文件格式的消息,您必需使用 Swing JEditorPane 或其它第三方 HTML 格式查看器组件。
if (message.getContentType().equals(“text/html”)) {
String content = (String)message.getContent();
JFrame frame = new JFrame();
JEditorPane text = new JEditorPane(“text/html”, content);
text.setEditable(false);
JScrollPane pane = new JScrollPane(text);
frame.getContentPane().add(pane);
frame.setSize(300, 300);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.show();
}
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-lauI8wc0-1715700247584)]
[外链图片转存中…(img-uuGKjqFj-1715700247585)]
[外链图片转存中…(img-w1agFZy5-1715700247585)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!