700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > Java Email-----使用Java程序实现收发电子邮件

Java Email-----使用Java程序实现收发电子邮件

时间:2019-10-30 20:56:14

相关推荐

Java Email-----使用Java程序实现收发电子邮件

前言:在完成使用Java程序实现收发电子邮件前,我们先来看一下传统的邮件是如何发送的:传统的邮件是通过邮局投递,然后从一个邮局到另一个邮局,最终到达用户的邮箱。

┌──────────┐ ┌──────────┐│PostOffice│ │PostOffice│.───.┌─────┐ ├──────────┤ ├──────────┤ ( ( )│═══ ░│───>│ ┌─┐ ┌┐┌┐ │───>│ ┌─┐ ┌┐┌┐ │───> `─┬─'└─────┘ │ │░│ └┘└┘ │ │ │░│ └┘└┘ │ │└─┴─┴──────┘ └─┴─┴──────┘ │

电子邮件的发送过程也是类似的,只不过是电子邮件是从用户电脑的邮件软件,例如Outlook,发送到邮件服务器上,可能经过若干个邮件服务器的中转,最终到达对方邮件服务器上,收件方就可以用软件接收邮件:

┌─────────┐ ┌─────────┐ ┌─────────┐│░░░░░░░░░│ │░░░░░░░░░│ │░░░░░░░░░│┌───────┐ ├─────────┤ ├─────────┤ ├─────────┤ ┌───────┐│░░░░░░░│ │░░░░░░░░░│ │░░░░░░░░░│ │░░░░░░░░░│ │░░░░░░░│├───────┤ ├─────────┤ ├─────────┤ ├─────────┤ ├───────┤│ │───>│O ░░░░░░░│───>│O ░░░░░░░│───>│O ░░░░░░░│<───│ │└───────┘ └─────────┘ └─────────┘ └─────────┘ └───────┘MUA MTA MTA MDA MUA

几个概念的理解:

MUA:Mail User Agent给用户服务的邮件代理(邮件软件)

MTA:Mail Transfer Agent 邮件中转的代理(邮件服务器)

MDA:Mail Delivery Agent邮件到达的代理(最终到达的邮件服务器)

电子邮件一旦到达MDA,就不再动了。实际上,电子邮件通常就存储在MDA服务器的硬盘上,然后等收件人通过软件或者登陆浏览器查看邮件。

准备SMTP登录信息

发送邮件前,我们首先要确定作为MTA的邮件服务器地址和端口号。邮件服务器地址通常是,端口号由邮件服务商确定使用25、465还是587。

常用邮件服务商的SMTP信息:

●QQ邮箱:SMTP服务器是,端口是465/587

●163邮箱:SMTP服务器是,端口是465

●126邮箱:SMTP服务器是,端口是25

●Gmail邮箱:SMTP服务器是,端口是465/587

准备好SMTP登录信息后,我们首先要把JavaMail相关的依赖Jar包javax.mail-1.6.2.jar加入至当前项目。

然后,我们通过JavaMail API连接到SMTP服务器上:以25端口为例,连接SMTP服务器时,需要准备一个Properties对象,填入相关信息。最后获取Session实例时,如果服务器需要认证,还需要传入一个Authenticator对象,并返回指定的用户名和口令。当我们获取到Session实例后,打开调试模式可以看到SMTP通信的详细内容,便于调试。

我们把获取Session实例的代码封装在JavaMailUtils类中,以此作为一个创建Session对象的工具类,通过静态方法creatSession()方便我们快速的创建Session对象。实现代码如下:

public class JavaMailUtils {public static Session creatSession() {// 服务器地址:String smtp = "";// 登录用户名:String username = "xxxxxxxxxxxx@";// 登录口令:String password = "xxxxxxxxxxxxxxxxxxxx";// 连接到SMTP服务器25端口:Properties props = new Properties();props.put("mail.smtp.host", smtp); // SMTP主机名props.put("mail.smtp.port", "25"); // 主机端口号props.put("mail.smtp.auth", "true"); // 是否需要用户认证props.put("mail.smtp.starttls.enable", "true"); // 启用TLS加密// 获取Session实例://参数1:SMTP服务器的连接信息//参数2:用户认证对象(Authenticator接口的匿名实现类)Session session = Session.getInstance(props, new Authenticator() {protected PasswordAuthentication getPasswordAuthentication() {return new PasswordAuthentication(username, password);}});// 设置debug模式便于调试:session.setDebug(true);return session;}}

发送邮件

发送邮件时,我们需要构造一个Message对象,然后调用Transport.send(Message)即可完成发送:绝大多数邮件服务器要求发送方地址和登录用户名必须一致,否则发送将失败。

try {Session session = JavaMailUtils.creatSession();MimeMessage message = new MimeMessage(session);// 设置发送方地址:message.setFrom(new InternetAddress("xxxxxxxxxxxxxx@"));// 设置接收方地址: TO主要收件人 CC抄送人message.setRecipient(Message.RecipientType.TO, new InternetAddress("xxxxxxxxxxxxx@"));// 设置邮件主题:message.setSubject("这是一封测试邮件", "UTF-8");// 设置邮件正文:message.setText("<b>爱你</b>孤身走暗巷...", "UTF-8","html");//邮件正文中包含有"html"标签(控制文本的格式)// 发送:Transport.send(message);} catch (AddressException e) {e.printStackTrace();} catch (MessagingException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}

填入真实的地址,运行上述代码,我们可以在控制台看到JavaMail打印的调试信息:

DEBUG: setDebug: JavaMail version 1.6.2DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle]DEBUG SMTP: need username and password for authenticationDEBUG SMTP: protocolConnect returning false, host=, user=Lenovo, password=<null>DEBUG SMTP: useEhlo true, useAuth trueDEBUG SMTP: trying to connect to host "", port 25, isSSL false220 Anti-spam GT for Coremail System (126com[0526])DEBUG SMTP: connected to host "", port: 25EHLO LAPTOP-250-mail250-PIPELINING250-AUTH LOGIN PLAIN XOAUTH2250-AUTH=LOGIN PLAIN XOAUTH2250-coremail 1Uxr2xKj7kG0xkI17xGrU7I0s8FY2U3Uj8Cz28x1UUUUU7Ic2I0Y2UFvE1abUCa0xDrUUUUj250-STARTTLS250-ID250 8BITMIMEDEBUG SMTP: Found extension "PIPELINING", arg ""DEBUG SMTP: Found extension "AUTH", arg "LOGIN PLAIN XOAUTH2"DEBUG SMTP: Found extension "AUTH=LOGIN", arg "PLAIN XOAUTH2"DEBUG SMTP: Found extension "coremail", arg "1Uxr2xKj7kG0xkI17xGrU7I0s8FY2U3Uj8Cz28x1UUUUU7Ic2I0Y2UFvE1abUCa0xDrUUUUj"DEBUG SMTP: Found extension "STARTTLS", arg ""DEBUG SMTP: Found extension "ID", arg ""DEBUG SMTP: Found extension "8BITMIME", arg ""STARTTLS220 Ready to start TLSEHLO LAPTOP-250-mail250-PIPELINING250-AUTH LOGIN PLAIN XOAUTH2250-AUTH=LOGIN PLAIN XOAUTH2250-coremail 1Uxr2xKj7kG0xkI17xGrU7I0s8FY2U3Uj8Cz28x1UUUUU7Ic2I0Y2UrxbFmDUCa0xDrUUUUj250-STARTTLS250-ID250 8BITMIMEDEBUG SMTP: Found extension "PIPELINING", arg ""DEBUG SMTP: Found extension "AUTH", arg "LOGIN PLAIN XOAUTH2"DEBUG SMTP: Found extension "AUTH=LOGIN", arg "PLAIN XOAUTH2"DEBUG SMTP: Found extension "coremail", arg "1Uxr2xKj7kG0xkI17xGrU7I0s8FY2U3Uj8Cz28x1UUUUU7Ic2I0Y2UrxbFmDUCa0xDrUUUUj"DEBUG SMTP: Found extension "STARTTLS", arg ""DEBUG SMTP: Found extension "ID", arg ""DEBUG SMTP: Found extension "8BITMIME", arg ""DEBUG SMTP: protocolConnect login, host=, user=tyqiqiiqiii@, password=<non-null>DEBUG SMTP: Attempt to authenticate using mechanisms: LOGIN PLAIN DIGEST-MD5 NTLM XOAUTH2 DEBUG SMTP: Using mechanism LOGINDEBUG SMTP: AUTH LOGIN command trace suppressedDEBUG SMTP: AUTH LOGIN succeededDEBUG SMTP: use8bit falseMAIL FROM:<tyqiqiiqiii@>250 Mail OKRCPT TO:<1601671085@>250 Mail OKDEBUG SMTP: Verified AddressesDEBUG SMTP: 1601671085@DATA354 End data with <CR><LF>.<CR><LF>Date: Sun, 17 Jul 16:58:47 +0800 (CST)From: tyqiqiiqiii@To: 1601671085@Message-ID: <2128227771.0.1658048327389@LAPTOP->Subject: =?UTF-8?B?6L+Z5piv5LiA5bCB5rWL6K+V6YKu5Lu2?=MIME-Version: 1.0Content-Type: text/html; charset=UTF-8Content-Transfer-Encoding: base64PGI+54ix5L2gPC9iPuWtpOi6q+i1sOaal+W3ty4uLg==.250 Mail OK queued as smtp1,C8mowACHnydGz9NieECmGw--.58834S3 1658048329DEBUG SMTP: message successfully delivered to mail serverQUIT221 Bye

从上面的调试信息可以看出,SMTP协议是一个请求-响应协议,客户端总是发送命令,然后等待服务器响应。服务器响应总是以数字开头,后面的信息才是用于调试的文本。这些响应码已经被定义在SMTP协议中了,查看具体的响应码就可以知道出错原因。

发送附件

要在电子邮件中携带附件,我们就不能直接调用message.setText()方法,而是要构造一个Multipart对象:

一个Multipart对象可以添加若干个BodyPart,其中第一个BodyPart是文本,即邮件正文,后面的BodyPart是附件。BodyPart依靠setContent()决定添加的内容,如果添加文本,用setContent("...", "text/plain;charset=utf-8")添加纯文本,或者用setContent("...", "text/html;charset=utf-8")添加HTML文本。如果添加附件,需要设置文件名(不一定和真实文件名一致),并且添加一个DataHandler(),传入文件的MIME类型。二进制文件可以用application/octet-stream,Word文档则是application/msword。

最后,通过setContent()把Multipart添加到Message中,即可发送。

// 创建MimeMessage邮件信息对象// ...略// 创建Multipart复合对象Multipart multipart = new MimeMultipart();// 添加text:BodyPart textpart = new MimeBodyPart();textpart.setContent(body, "text/html;charset=utf-8");multipart.addBodyPart(textpart);// 添加image:BodyPart imagepart = new MimeBodyPart();imagepart.setFileName(附件名称);imagepart.setDataHandler(new DataHandler(new ByteArrayDataSource(文件流字节数组, "application/octet-stream")));multipart.addBodyPart(imagepart);// 设置邮件内容为multipart:message.setContent(multipart);

发送内嵌图片的HTML邮件

如果需要在HTML邮件中内嵌图片,可以选择在邮件中加入<img src="/test.jpg">,这样的外部图片链接通常会被邮件客户端过滤,并提示用户显示图片并不安全。只有内嵌的图片才能正常在邮件中显示。所以,这种方式并不推荐。

推荐将内嵌图片作为一个附件嵌入邮件,即邮件本身也是Multipart,但需要做一点额外的处理:

//邮件内容"复合"对象Multipart multipart=new MimeMultipart();//正文BodyPart textPart = new MimeBodyPart();StringBuilder body=new StringBuilder();body.append("<h1>猫</h1>");body.append("<img src=\"cid:cat\"/>");//通过内容id引用附件图片//参数1:正文内容//参数2:内容类型;字符编码集textPart.setContent(body.toString(),"text/html;charset=utf-8");//附件BodyPart imagePart = new MimeBodyPart();imagePart.setFileName("cat.jpg");//设置附件文件的显示名称//数据处理对象(读取附件文件从本地磁盘进行读取)imagePart.setDataHandler(new DataHandler(new ByteArrayDataSource(Files.readAllBytes(Paths.get("E:\\picture\\8504221.jpg")), "application/octet-stream")));imagePart.setHeader("Content-ID","<cat>");//设置内容id//添加至邮件内容multipart.addBodyPart(textPart);//添加正文multipart.addBodyPart(imagePart);//添加附件//设置邮件内容message.setContent(multipart);

以上是最近学习中收获知识的一点小总结,如果对你有帮助,请留下你的点赞和关注,谢谢!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。