用Java Socket实现SMTP邮件发送

目录:

  • 1、邮件基础概念
  • 2、Java Mail API介绍
  • 3、收发邮件代码示例

PS:如果你想直接拿代码用,可以直接跳到第3部分。

**

一、邮件基础概念

**

1.1 邮件服务器和电子邮箱

要在Internet上提供电子邮件功能,必须有专门的电子邮件服务器。例如现在Internet很多提供邮件服务的厂商:sina、sohu、163等等他们都有自己的邮件服务器。

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

电子邮箱(E-Mail地址)的获得需要在邮件服务器上进行申请,确切地说,电子邮箱其实就是用户在邮件服务器上申请的一个账户,用户在邮件服务器上申请了一个帐号后,邮件服务器就会为这个账号分配一定的空间,用户从而可以使用这个帐号以及空间发送电子邮件和保存别人发送过来的电子邮件。

1.2 邮件相关的协议

  • 简单邮件传输协议(Simple Mail Transfer PRotocol,SMTP)是一个运行在TCP/ip之上的协议,用它发送和接收电子邮件。SMTP 服务器在默认端口25上监听。SMTP客户使用一组简单的、基于文本的命令与SMTP服务器进行通信。在建立了一个连接后,为了接收响应,SMTP客户首先发出一个命令来标识它们的电子邮件地址。假如SMTP服务器接受了发送者发出的文本命令,它就利用一个OK响应和整数代码确认每一个命令。客户发送的另一个命令意味着电子邮件消息体的开始,消息体以一个圆点“.”加上回车符终止。

  • 邮局协议(Post Office Protocol Version 3,POP3)提供了一种对邮件消息进行排队的标准机制,这样接收者以后才能检索邮件。POP3服务器也运行在TCP/IP之上,并且在默认端口110上监听。在客户和服务器之间进行了初始的会话之后,基于文本的命令序列可以被交换。POP3客户利用用户名和口令向POP3服务器认证。POP3中的认证是在一种未加密的会话基础之上进行的。POP3客户发出一系列命令发送给POP3服务器,如:请求客户邮箱队列的状态、请求列出的邮箱队列的内容和请求检索实际的消息。POP3代表一种存储转发类型的消息传递服务。现在,大部分邮件服务器都采用SMTP发送邮件,同时使用POP3接收电子邮件消息。

  • Internet 消息访问协议(Internet Message access Protocol,IMAP)是一种电子邮件消息排队服务,它对POP3的存储转发限制提供了重要的改进。IMAP也使用基于文本命令的语法在TCP/IP上运行,IMAP服务器一般在默认端口143监听。IMAP服务器答应IMAP客户下载一个电子邮件的头信息,并且不要求将整个消息从服务器下载至客户,这一点与POP3是相同的。IMAP服务器提供了一种排队机制以接收消息,同时必须与SMTP相结合在一起才能发送消息。

这三种协议都有对应SSL加密传输的协议,分别是 SMTPS,POP3S 和 IMAPS 。

MIME(Multipurpose Internet Mail Extensions)
:即多用途因特网邮件扩展标准。它不是邮件传输协议。但对传输内容的消息、附件及其它的内容定义了格式。

1.3 电子邮件的发送和接收过程

通过一张图来说明一封邮件的发送和接收过程,如下图所示:

在这里插入图片描述

简单说一下这个邮件收发过程:

1、xdp@sohu.com 用户写好一封Email发送到sohu的Smtp服务器。对应于上图的步骤①

2、sohu的Smtp服务器开始处理xdp@sohu.com 用户的请求,它会根据收件人的地址判断,当前收件人是不是自己管辖的用户,如果是,就直接将Email存放到为该收件人的分配的邮箱空间当中。sohu的Smtp服务器判断收件人地址发现,这一封Email的收件人gacl@sina.com 是Sina的邮件服务器管理的,于是又将Email转发给Sina的Smtp服务器。对应于上图的步骤②

3、Sina的Smtp服务器开始处理sohu的Smtp服务器发送过来的Email,Sina的Smtp服务器根据收件人的地址判断,发现收件人自己管辖的用户,于是就直接将Email存放到为gacl@sina.com 用户的分配的邮箱空间当中。对应于上图的步骤③。

4、xdp@sohu.com 用户将邮件发出去之后,就通知gacl@sina.com 用户去收取。gacl@sina.com 用户于是就连接上Sina的POP3服务器收取邮件,对应于上图的步骤④。

5、POP3服务器从gacl@sina.com 用户的邮箱空间当中取出Email,对应于步骤⑤。

6、POP3服务器将取出来的Email发给gacl@sina.com 用户,对应于步骤⑥。

**

二、Java Mail API

**

JavaMail 是由 Sun 发布的用来处理 email 的 API 。它并没有包含在 Java SE 中,而是作为 Java EE 的一部分。

mail.jar :此 JAR 文件包含 JavaMail API 和 Sun 提供的 SMTP 、 IMAP 和 POP3 服务提供程序;

activation.jar :此 JAR 文件包含 JAF API 和 Sun 的实现。

JavaMail 包中用于处理电子邮件的核心类是: Properties 、 Session 、 Message 、 Address 、 Authenticator 、 Transport 、 Store 等。

2.1、Java mail 传输过程

在这里插入图片描述

如上图,电子邮件的处理步骤如下:

  • 创建一个 Session 对象。
  • Session 对象创建一个 Transport 对象 /Store 对象,用来发送 / 保存邮件。
  • Transport 对象 /Store 对象连接邮件服务器。
  • Transport 对象 /Store 对象创建一个 Message 对象 ( 也就是邮件内容 ) 。
  • Transport 对象发送邮件; Store 对象获取邮箱的邮件。

2.2、JavaMail 的核心类

JavaMail 对收发邮件进行了高级的抽象,形成了一些关键的的接口和类,它们构成了程序的基础,下面我们分别来了解一下这些最常见的对象。

2.2.1 java.util.Properties 类 ( 属性对象 )

java.util.Properties 类代表一组属性集合。

它的每一个键和值都是 String 类型。

由于 JavaMail 需要和邮件服务器进行通信,这就要求程序提供许多诸如服务器地址、端口、用户名、密码等信息, JavaMail 通过 Properties 对象封装这些属性信息。

例: 如下面的代码封装了几个属性信息:

Properties prop = new Properties();
prop.setProperty("mail.debug", "true");
prop.setProperty("mail.host", "[email protected]");
prop.setProperty("mail.transport.protocol", "smtp");
prop.setProperty("mail.smtp.auth", "true");

针对不同的的邮件协议, JavaMail 规定了服务提供者必须支持一系列属性,

下表是一些常见属性(属性值都以 String 类型进行设置,属性类型栏仅表示属性是如何被解析的):

在这里插入图片描述

2.2.2、javax.mail.Session 类 ( 会话对象 )

Session 表示一个邮件会话。

Session 的主要作用包括两个方面:

接收各种配置属性信息:通过 Properties 对象设置的属性信息;

初始化 JavaMail 环境:根据 JavaMail 的配置文件,初始化 JavaMail 环境,以便通过 Session 对象创建其他重要类的实例。

JavaMail 在 Jar 包的 META-INF 目录下,通过以下文件提供了基本配置信息,以便 session 能够根据这个配置文件加载提供者的实现类:

javamail.default.providers ;

javamail.default.address.map 。

在这里插入图片描述

例:

Properties props = new Properties();
props.setProperty("mail.transport.protocol", "smtp");
Session session = Session.getInstance(props);

2.2.3、javax.mail.Transport 类 ( 邮件传输 )

邮件操作只有发送或接收两种处理方式。

JavaMail 将这两种不同操作描述为传输( javax.mail.Transport )和存储( javax.mail.Store ),传输对应邮件的发送,而存储对应邮件的接收。

getTransport : Session 类中的 getTransport () 有多个重载方法,可以用来创建 Transport 对象。

connect : 如果设置了认证命令—— mail.smtp.auth ,那么使用 Transport 类的 connect 方法连接服务器时,则必须加上用户名和密码。

sendMessage : Transport 类的 sendMessage 方法用来发送邮件消息。

close : Transport 类的 close 方法用来关闭和邮件服务器的连接。

2.2.4、javax.mail.Store 类 ( 邮件存储 )

getStore : Session 类中的 getStore () 有多个重载方法,可以用来创建 Store 对象。

connect : 如果设置了认证命令—— mail.smtp.auth ,那么使用 Store 类的 connect 方法连接服务器时,则必须加上用户名和密码。

getFolder : Store 类的 getFolder 方法可以 获取邮箱内的邮件夹 Folder 对象

close : Store 类的 close 方法用来关闭和邮件服务器的连接。

2.2.5、javax.mail.Message( 消息对象 )

javax.mail.Message 是个抽象类,只能用子类去实例化,多数情况下为 javax.mail.internet.MimeMessage 。

MimeMessage 代表 MIME 类型的电子邮件消息。

要创建一个 Message ,需要将 Session 对象传递给 MimeMessage 构造器:

MimeMessage message = new MimeMessage(session);

注意:还存在其它构造器,如用按 RFC822 格式的输入流来创建消息。

setFrom :设置邮件的发件人

setRecipient :设置邮件的发送人、抄送人、密送人

三种预定义的地址类型是:

Message.RecipientType.TO :收件人

Message.RecipientType.CC :抄送人

Message.RecipientType.BCC :密送人

setSubject :设置邮件的主题

setContent :设置邮件内容

setText :如果邮件内容是纯文本,可以使用此接口设置文本内容。

MimeMessage结构介绍:

MimeMessage 类:代表整封邮件。

MimeBodyPart 类:代表邮件的一个 MIME 信息。

MimeMultipart 类:代表一个由多个 MIME 信息组合成的组合 MIME 信息。

在这里插入图片描述

2.2.6、javax.mail.Address( 地址 )

一旦您创建了 Session 和 Message ,并将内容填入消息后,就可以用 Address 确定信件地址了。和 Message 一样, Address 也是个抽象类。您用的是 javax.mail.internet.InternetAddress 类。

若创建的地址只包含电子邮件地址,只要传递电子邮件地址到构造器就行了。

例:

Address address = new InternetAddress("[email protected]");

2.2.7、 Authenticator :认证者

与 java.net 类一样, JavaMail API 也可以利用 Authenticator 通过用户名和密码访问受保护的资源。对于 JavaMail API 来说,这些资源就是邮件服务器。 JavaMail Authenticator 在 javax.mail 包中,而且它和 java.net 中同名的类 Authenticator 不同。两者并不共享同一个 Authenticator ,因为 JavaMail API 用于 Java 1.1 ,它没有 java.net 类别。

要使用 Authenticator ,先创建一个抽象类的子类,并从 getPasswordAuthentication() 方法中返回 PasswordAuthentication 实例。创建完成后,您必需向 session 注册 Authenticator 。然后,在需要认证的时候,就会通知 Authenticator 。您可以弹出窗口,也可以从配置文件中(虽然没有加密是不安全的)读取用户名和密码,将它们作为 PasswordAuthentication 对象返回给调用程序。

例:

Properties props = new Properties();
Authenticator auth = new MyAuthenticator();
Session session = Session.getDefaultInstance(props, auth);

**

三、收发邮件代码示例

**

3.1 发送文本邮件

 public static void main(String[] args) throws Exception {Properties prop = new Properties();prop.setProperty("mail.debug", "true");prop.setProperty("mail.host", MAIL_SERVER_HOST);prop.setProperty("mail.transport.protocol", "smtp");prop.setProperty("mail.smtp.auth", "true");// 1、创建sessionSession session = Session.getInstance(prop);Transport ts = null;// 2、通过session得到transport对象ts = session.getTransport();// 3、连上邮件服务器ts.connect(MAIL_SERVER_HOST, USER, PASSWORD);// 4、创建邮件MimeMessage message = new MimeMessage(session);// 邮件消息头message.setFrom(new InternetAddress(MAIL_FROM)); // 邮件的发件人message.setRecipient(Message.RecipientType.TO, new InternetAddress(MAIL_TO)); // 邮件的收件人message.setRecipient(Message.RecipientType.CC, new InternetAddress(MAIL_CC)); // 邮件的抄送人message.setRecipient(Message.RecipientType.BCC, new InternetAddress(MAIL_BCC)); // 邮件的密送人message.setSubject("测试文本邮件"); // 邮件的标题// 邮件消息体message.setText("天下无双。");// 5、发送邮件ts.sendMessage(message, message.getAllRecipients());ts.close();
}

3.2 发送 HTML 格式的邮件

public static void main(String[] args) throws Exception {Properties prop = new Properties();prop.setProperty("mail.debug", "true");prop.setProperty("mail.host", MAIL_SERVER_HOST);prop.setProperty("mail.transport.protocol", "smtp");prop.setProperty("mail.smtp.auth", "true");// 1、创建sessionSession session = Session.getInstance(prop);Transport ts = null;// 2、通过session得到transport对象ts = session.getTransport();// 3、连上邮件服务器ts.connect(MAIL_SERVER_HOST, USER, PASSWORD);// 4、创建邮件MimeMessage message = new MimeMessage(session);// 邮件消息头message.setFrom(new InternetAddress(MAIL_FROM)); // 邮件的发件人message.setRecipient(Message.RecipientType.TO, new InternetAddress(MAIL_TO)); // 邮件的收件人message.setRecipient(Message.RecipientType.CC, new InternetAddress(MAIL_CC)); // 邮件的抄送人message.setRecipient(Message.RecipientType.BCC, new InternetAddress(MAIL_BCC)); // 邮件的密送人message.setSubject("测试HTML邮件"); // 邮件的标题String htmlContent = "<h1>Hello</h1>" + "<p>显示图片<img src='cid:abc.jpg'>1.jpg</p>";MimeBodyPart text = new MimeBodyPart();text.setContent(htmlContent, "text/html;charset=UTF-8");MimeBodyPart image = new MimeBodyPart();DataHandler dh = new DataHandler(new FileDataSource("D://[04]Temp//img//1.jpg"));image.setDataHandler(dh);image.setContentID("abc.jpg");// 描述数据关系MimeMultipart mm = new MimeMultipart();mm.addBodyPart(text);mm.addBodyPart(image);mm.setSubType("related");message.setContent(mm);message.saveChanges();// 5、发送邮件ts.sendMessage(message, message.getAllRecipients());ts.close();
}

3.3 发送带附件的邮件

public static void main(String[] args) throws Exception {Properties prop = new Properties();prop.setProperty("mail.debug", "true");prop.setProperty("mail.host", MAIL_SERVER_HOST);prop.setProperty("mail.transport.protocol", "smtp");prop.setProperty("mail.smtp.auth", "true");// 1、创建sessionSession session = Session.getInstance(prop);Transport ts = null;// 2、通过session得到transport对象ts = session.getTransport();// 3、连上邮件服务器ts.connect(MAIL_SERVER_HOST, USER, PASSWORD);// 4、创建邮件MimeMessage message = new MimeMessage(session);// 邮件消息头message.setFrom(new InternetAddress(MAIL_FROM)); // 邮件的发件人message.setRecipient(Message.RecipientType.TO, new InternetAddress(MAIL_TO)); // 邮件的收件人message.setRecipient(Message.RecipientType.CC, new InternetAddress(MAIL_CC)); // 邮件的抄送人message.setRecipient(Message.RecipientType.BCC, new InternetAddress(MAIL_BCC)); // 邮件的密送人message.setSubject("测试带附件邮件"); // 邮件的标题MimeBodyPart text = new MimeBodyPart();text.setContent("邮件中有两个附件。", "text/html;charset=UTF-8");// 描述数据关系MimeMultipart mm = new MimeMultipart();mm.setSubType("related");mm.addBodyPart(text);String[] files = {"D://[04]Temp//img//1.jpg", "D://[04]Temp//img//2.jpg"};// 添加邮件附件for (String filename : files) {MimeBodyPart attachPart = new MimeBodyPart();attachPart.attachFile(filename);mm.addBodyPart(attachPart);}message.setContent(mm);message.saveChanges();// 5、发送邮件ts.sendMessage(message, message.getAllRecipients());ts.close();
}

3.4 获取邮箱中的邮件

public class StoreMail {final static String USER = "robot"; // 用户名final static String PASSWORD = "password520"; // 密码public final static String MAIL_SERVER_HOST = "mail.***.com"; // 邮箱服务器public final static String TYPE_HTML = "text/html;charset=UTF-8"; // 文本内容类型public final static String MAIL_FROM = "[email protected]"; // 发件人public final static String MAIL_TO = "[email protected]"; // 收件人public final static String MAIL_CC = "[email protected]"; // 抄送人public final static String MAIL_BCC = "[email protected]"; // 密送人public static void main(String[] args) throws Exception {// 创建一个有具体连接信息的Properties对象Properties prop = new Properties();prop.setProperty("mail.debug", "true");prop.setProperty("mail.store.protocol", "pop3");prop.setProperty("mail.pop3.host", MAIL_SERVER_HOST);// 1、创建sessionSession session = Session.getInstance(prop);// 2、通过session得到Store对象Store store = session.getStore();// 3、连上邮件服务器store.connect(MAIL_SERVER_HOST, USER, PASSWORD);// 4、获得邮箱内的邮件夹Folder folder = store.getFolder("inbox");folder.open(Folder.READ_ONLY);// 获得邮件夹Folder内的所有邮件Message对象Message[] messages = folder.getMessages();for (int i = 0; i < messages.length; i++) {String subject = messages[i].getSubject();String from = (messages[i].getFrom()[0]).toString();System.out.println("第 " + (i + 1) + "封邮件的主题:" + subject);System.out.println("第 " + (i + 1) + "封邮件的发件人地址:" + from);}// 5、关闭folder.close(false);store.close();}
}

3.5 转发邮件

例:获取指定邮件夹下的第一封邮件并转发

public static void main(String[] args) throws Exception {Properties prop = new Properties();prop.put("mail.store.protocol", "pop3");prop.put("mail.pop3.host", MAIL_SERVER_HOST);prop.put("mail.pop3.starttls.enable", "true");prop.put("mail.smtp.auth", "true");prop.put("mail.smtp.host", MAIL_SERVER_HOST);// 1、创建sessionSession session = Session.getDefaultInstance(prop);// 2、读取邮件夹Store store = session.getStore("pop3");store.connect(MAIL_SERVER_HOST, USER, PASSWORD);Folder folder = store.getFolder("inbox");folder.open(Folder.READ_ONLY);// 获取邮件夹中第1封邮件信息Message[] messages = folder.getMessages();if (messages.length <= 0) {return;}Message message = messages[0];// 打印邮件关键信息String from = InternetAddress.toString(message.getFrom());if (from != null) {System.out.println("From: " + from);}String replyTo = InternetAddress.toString(message.getReplyTo());if (replyTo != null) {System.out.println("Reply-to: " + replyTo);}String to = InternetAddress.toString(message.getRecipients(Message.RecipientType.TO));if (to != null) {System.out.println("To: " + to);}String subject = message.getSubject();if (subject != null) {System.out.println("Subject: " + subject);}Date sent = message.getSentDate();if (sent != null) {System.out.println("Sent: " + sent);}// 设置转发邮件信息头Message forward = new MimeMessage(session);forward.setFrom(new InternetAddress(MAIL_FROM));forward.setRecipient(Message.RecipientType.TO, new InternetAddress(MAIL_TO));forward.setSubject("Fwd: " + message.getSubject());// 设置转发邮件内容MimeBodyPart bodyPart = new MimeBodyPart();bodyPart.setContent(message, "message/rfc822");Multipart multipart = new MimeMultipart();multipart.addBodyPart(bodyPart);forward.setContent(multipart);forward.saveChanges();Transport ts = session.getTransport("smtp");ts.connect(USER, PASSWORD);ts.sendMessage(forward, forward.getAllRecipients());folder.close(false);store.close();ts.close();System.out.println("message forwarded successfully....");
}

3.6 收发完整示例

3.6.1 邮件服务器 MailServer.java

import java.util.List;
import java.util.Properties;import javax.mail.Authenticator;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMessage.RecipientType;/*** 简单邮件发送器,可单发,群发。* * @author humingfeng* */
public class MailServer {/*** 发送邮件的props文件*/private final transient Properties props = System.getProperties();/*** 邮件服务器登录验证*/private transient MailAuthenticator authenticator;/*** 邮箱session*/private transient Session session;/*** 初始化邮件发送器* * @param smtpHostName*            SMTP邮件服务器地址* @param username*            发送邮件的用户名(地址)* @param password*            发送邮件的密码*/public MailServer(final String smtpHostName, final String username,final String password) {init(username, password, smtpHostName);}/*** 初始化邮件发送器* * @param username*            发送邮件的用户名(地址),并以此解析SMTP服务器地址* @param password*            发送邮件的密码*/public MailServer(final String username, final String password) {// 通过邮箱地址解析出smtp服务器,对大多数邮箱都管用final String smtpHostName = "smtp." + username.split("@")[1];init(username, password, smtpHostName);}/*** 初始化* * @param username*            发送邮件的用户名(地址)* @param password*            密码* @param smtpHostName*            SMTP主机地址*/private void init(String username, String password, String smtpHostName) {// 初始化propsprops.put("mail.smtp.auth", "true");props.put("mail.smtp.host", smtpHostName);if(smtpHostName==null)props.put("mail.smtp.host", smtpHostName);// 验证authenticator = new MailAuthenticator(username, password);// 创建sessionsession = Session.getInstance(props, authenticator);}/*** 发送邮件* * @param recipient*            收件人邮箱地址* @param subject*            邮件主题* @param content*            邮件内容* @throws AddressException* @throws MessagingException*/public void send(String recipient, String subject, Object content)throws AddressException, MessagingException {// 创建mime类型邮件final MimeMessage message = new MimeMessage(session);// 设置发信人message.setFrom(new InternetAddress(authenticator.getUsername()));// 设置收件人if(recipient!=null&&recipient.indexOf(";")!=-1){//多收件人String[] rec = recipient.split(";");int len = rec.length;InternetAddress[] iad = new InternetAddress[len];for(int i=0; i<len; i++){iad[i] =  new InternetAddress(rec[i]);}message.setRecipients(RecipientType.TO, iad);}else{//单收件人message.setRecipient(RecipientType.TO, new InternetAddress(recipient));}// 设置主题message.setSubject(subject);// 设置邮件内容message.setContent(content.toString(), "text/html;charset=utf-8");
//		message.setText(content.toString(), "GBK");// 发送Transport.send(message);}/*** 群发邮件* * @param recipients*            收件人们* @param subject*            主题* @param content*            内容* @throws AddressException* @throws MessagingException*/public void send(List<String> recipients, String subject, Object content)throws AddressException, MessagingException {// 创建mime类型邮件final MimeMessage message = new MimeMessage(session);// 设置发信人message.setFrom(new InternetAddress(authenticator.getUsername()));// 设置收件人们final int num = recipients.size();InternetAddress[] addresses = new InternetAddress[num];for (int i = 0; i < num; i++) {addresses[i] = new InternetAddress(recipients.get(i));}message.setRecipients(RecipientType.TO, addresses);// 设置主题message.setSubject(subject);// 设置邮件内容message.setContent(content.toString(), "text/html;charset=utf-8");// 发送Transport.send(message);}/*** 服务器邮箱登录验证* * @author MZULE* */public class MailAuthenticator extends Authenticator {/*** 用户名(登录邮箱)*/private String username;/*** 密码*/private String password;/*** 初始化邮箱和密码* * @param username*            邮箱* @param password*            密码*/public MailAuthenticator(String username, String password) {this.username = username;this.password = password;}String getPassword() {return password;}@Overrideprotected PasswordAuthentication getPasswordAuthentication() {return new PasswordAuthentication(username, password);}String getUsername() {return username;}public void setPassword(String password) {this.password = password;}public void setUsername(String username) {this.username = username;}}
}

3.6.2 SendClient

import javax.mail.MessagingException;
import javax.mail.internet.AddressException;/*** @author **/
public class MailSender {/*** 服务邮箱*/private static MailServer mailServer = null;//private static String userName;private static String password;private static String stmp;/*** @param userName the userName to set*/public void setUserName(String userName) {if(MailSender.userName==null)MailSender.userName = userName;}/*** @param password the password to set*/public void setPassword(String password) {if(MailSender.password==null)MailSender.password = password;}/*** @param stmp the stmp to set*/public void setStmp(String stmp) {if(MailSender.stmp==null)MailSender.stmp = stmp;}/*** 使用默认的用户名和密码发送邮件* @param recipient* @param subject* @param content* @throws MessagingException * @throws AddressException */public static void sendHtml(String recipient, String subject, Object content) throws AddressException, MessagingException{if (mailServer == null) mailServer = new MailServer(stmp,userName,password);mailServer.send(recipient, subject, content);}/*** 使用指定的用户名和密码发送邮件* @param server* @param password* @param recipient* @param subject* @param content* @throws MessagingException * @throws AddressException */public static void sendHtml(String server,String password,String stmpIp, String recipient, String subject, Object content) throws AddressException, MessagingException{new MailServer(stmpIp,server,password).send(recipient, subject, content);}public static void main(String[] args) {try {String s = "ceshi2:<br/>您好,我在给你们演示发邮件看见了没.";sendHtml("humf@vip.qq.com","password","IP", "humf@vip.qq.com", "我是是是", s);} catch (AddressException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (MessagingException e) {// TODO Auto-generated catch blocke.printStackTrace();}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/313705.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微软开源新字体Cascadia Code,源于Windows Terminal

微软开源了一套新的字体 Cascadia Code。Cascadia Code 是微软在 5 月份的 Build 大会上宣布推出的等宽字体&#xff0c;微软介绍它是与新的终端 Windows Terminal 一起开发的&#xff0c;官方建议将其与终端应用和 VS、VS Code 等文本编辑器一起使用。Cascadia Code 为命令行和…

进程间通讯的7种方式

1、常见的通信方式 管道pipe&#xff1a;管道是一种半双工的通信方式&#xff0c;数据只能单向流动&#xff0c;而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。命名管道FIFO&#xff1a;有名管道也是半双工的通信方式&#xff0c;但是它允许无亲缘…

官宣!VS Code Python 全新功能在 PyCon China 全球首发!

北京时间 2019 年 9 月 21 日&#xff0c;PyCon China 2019 在上海举行。在下午的演讲中&#xff0c;来自微软开发工具事业部的资深研发工程师在演讲中&#xff0c;我们看到了 Azure Notebook 与 VS Code 对 Python 的强大的支持。然而&#xff0c;鱼和熊掌似乎不可兼得。Jupyt…

什么是CDN

一、cdn简介 CDN的全称是Content Delivery Network&#xff0c;即内容分发网络。其目的是通过在现有的internet中增加一层新的网络架构&#xff0c;将网站的内容发布到最接近用户的网络边缘&#xff0c;使用户可以就近取得所需的内容&#xff0c;提高用户访问网站的响应速度。…

高性能最终一致性框架Ray之基本概念原理

一、Actor介绍Actor是一种并发模型&#xff0c;是共享内存并发模型的替代方案。共享内存模型的缺点&#xff1a;共享内存模型使用各种各样的锁来解决状态竞争问题&#xff0c;性能低下且让编码变得复杂和容易出错。共享内存受限于单节点的服务器资源限制。Actor模型的优点&…

漫画:程序员带娃日常(1)

我是一名IT界资深人士做过乙方苦哈哈做过甲方做过项目、搞点管理做过培训、也上台演讲不过现在最大挑战、交期最长的项目是。。。带 娃娃子啊&#xff0c;爸爸也是第一次当爸爸&#xff0c;要请你多多指教啦&#xff01;1“小刘&#xff0c;把这个需求细化一下。”“兄弟们&…

表达式树练习实践:入门基础

什么是表达式树来自微软官方文档的定义&#xff1a;表达式树以树形数据结构表示代码。它能干什么呢&#xff1f;你可以对表达式树中的代码进行编辑和运算。这样能够动态修改可执行代码、在不同数据库中执行 LINQ 查询以及创建动态查询。好不好玩&#xff1f;表达式树还能用于动…

Servlet与线程安全

Servlet与线程安全 先说结论&#xff0c;Servlet本身是单例的&#xff0c;线程安全的。但是如果引入共享变量&#xff0c;则可能会变得线程不安全。 1. 什么是线程安全 首先说明一下对线程安全的讨论&#xff0c;哪种情况我们可以称作线程安全&#xff1f; 《Java并发编程实…

尝鲜体验 VS Code Python 原生 Jupyter Notebook 支持

9 月 21 日&#xff0c;PyCon China 2019 在上海举办。微软的 VS Code 发布了原生的Juypter Notebook 支持。 虽然要等到月底 Marketplace 里面才会正式更新&#xff0c;但 GitHub 上的 repo 已经包含了相应的 commit&#xff0c;所以还是可以通过手动安装的方式尝鲜。现有 VSC…

Java Web之filter、listener、Interceptor

** 1、Servlet ** Servlet 是服务端的 Java 应用程序&#xff0c;用于处理HTTP请求&#xff0c;做出相应的响应。 当客户端向服务器发出HTTP请求时&#xff0c;首先会由服务器中的 Web 容器&#xff08;如Tomcat&#xff09;对请求进行路由&#xff0c;交给该URL对应的 Servl…

abp vNext微服务框架分析

abp vNext新框架的热度一直都很高&#xff0c;于是最近上手将vNext的微服务Demo做了一番研究。我的体验是&#xff0c;vNext的微服务架构确实比较成熟&#xff0c;但是十分难以上手&#xff0c;对于没有微服务开发经验的.net人员来说几乎是看不懂的&#xff0c;所以研究一番后再…

.NET Conf 2019日程(北京时间)

一年一度的 .NET Conf马上就要开始了,我将日程简易的翻译了一下,并且时间全部转换为北京时间,以方便国内.NETer.第1天 (北京时间9月24日).NET Conf 2019 基调 - Scott Hunter Mads Torgersen James Montemagno Olia Gavrysh Daniel Roth Glenn Condron Bri Achtman欢迎来到 .NE…

Hibernate基础

** 一、什么是Hibernate&#xff1f; **   Hibernate是一个轻量级的ORMapping框架   ORMapping原理&#xff08;Object Relational Mapping&#xff09; ORMapping基本对应规则&#xff1a; 1&#xff1a;类跟表相对应2&#xff1a;类的属性跟表的字段相对应3&#xff1…

进击的.NET 在云原生时代的蜕变

你一定看过这篇文章 《进击的 Java &#xff0c;云原生时代的蜕变》, 本篇文章的灵感来自于这篇文章。北京时间9.24 就将正式发布.NET Core 3.0, 所以写下这篇文章让大家全面认识.NET Core。.NET 生态系统是一个不断变化的生态圈&#xff0c;我相信它正在朝着一个伟大的方向发…

Hibernate懒加载问题的5种解决方案

** 1、Hibernate基础 ** Hibernate基础&#xff0c;传送门 ** 2、什么是Hibernate懒加载 ** 当我们查询一个对象的时候&#xff0c;在默认情况下&#xff0c;返回的只是该对象的代理对象&#xff0c;当用户去使用该对象的属性时&#xff0c;才会向数据库再一次发出查询语…

程序员过关斩将--要想获取我的用户信息,就得按照规矩来

菜菜君&#xff0c;我又来啦又有什么事吗&#xff1f;我按照你上篇文章写的JWT的方式已经把网站认证写完了&#xff0c;而且效果还不错那恭喜你呀&#xff0c;下次面试又多了一项技能不过&#xff0c;现在又有一个问题&#xff0c;我做的系统有一个合作商想要利用我们的用户信息…

E. Surprise me!(莫比乌斯反演 + 虚树 DP)

E. Surprise me! ∑i1n∑j1nϕ(aiaj)d(i,j)设paii∑i1n∑j1nϕ(ij)d(pi,pj)∑i1n∑j1nϕ(i)ϕ(j)ϕ(gcd⁡(i,j))gcd⁡(i,j)d(pi,pj)∑d1ndϕ(d)∑i1nd∑j1ndϕ(id)ϕ(jd)d(pid,pjd)[gcd⁡(i,j)1]∑d1ndϕ(d)∑k1ndμ(k)∑i1nkd∑j1nkdϕ(ikd)ϕ(jkd)d(pikd,pjkd)Tkd∑T1n(∑i1n…

Hibernate 的缓存机制

** 1、Hibernate 应用程序中按照缓存的范围&#xff0c;可以将缓存分为三类 ** &#xff08;1.1&#xff09;事务范围缓存&#xff08;单Session&#xff0c;即一级缓存&#xff09; 事务范围的缓存只能被当前事务访问&#xff0c;每个事务都有各自的缓存。缓存的生命周期依…

.NET分布式大规模计算利器-Orleans(一)

写在前面Orleans是基于Actor模型思想的.NET领域的框架&#xff0c;它提供了一种直接而简单的方法来构建分布式大规模计算应用程序&#xff0c;而无需学习和应用复杂的并发或其他扩展模式。我在2015年下半年开始应用Orleans&#xff0c;当时公司的交易系统采用的架构就是基于Orl…

从单机应用到微服务,用户认证走几步?

用户认证指在用户访问服务的时候确认用户的身份&#xff0c;受限于HTTP无状态的特性&#xff0c;应用开发者需要自行实现用户认证相关功能。通常是用户登录时服务端生成通行证返回给客户端&#xff0c;客户端在接下来的请求中携带通行证&#xff0c;然后服务端通过校验该通行证…