JavaMail示例–使用SMTP以Java发送邮件
今天,我们将研究JavaMail Example在Java程序中发送电子邮件。
发送电子邮件是现实生活中应用程序中的常见任务之一,这就是Java提供可靠的JavaMail API的原因,我们可以使用它来使用SMTP服务器发送电子邮件。
JavaMail API支持TLS和SSL身份验证来发送电子邮件。
JavaMail示例
今天,我们将学习如何使用JavaMail API通过不带身份验证,TLS和SSL身份验证的SMTP服务器发送电子邮件,以及如何发送附件以及在电子邮件正文中附加和使用图像。
对于TLS和SSL身份验证,我使用的是GMail SMTP服务器,因为它同时支持两者。
JavaMail API不是标准JDK的一部分,因此您必须从其官方(即JavaMail主页)下载它。
下载最新版本的JavaMail参考实现,并将其包含在项目构建路径中。
jar文件的名称将为javax.mail.jar。
如果您正在使用基于Maven的项目,只需在项目中添加以下依赖项。
<dependency> <groupId>com.sun.mail</groupId> <artifactId>javax.mail</artifactId> <version>1.5.5</version> </dependency>
发送电子邮件的Java程序包含以下步骤:
创建
javax.mail.Session
对象创建
javax.mail.internet.MimeMessage
对象时,我们必须在此对象中设置不同的属性,例如收件人电子邮件地址,电子邮件主题,回复电子邮件,电子邮件正文,附件等。使用
javax.mail.Transport
发送电子邮件。
创建会话的逻辑因SMTP服务器的类型而异,例如,如果SMTP服务器不需要任何身份验证,我们可以创建具有一些简单属性的Session对象,而如果它需要TLS或者SSL身份验证,则创建逻辑将有所不同。
因此,我将创建一个包含一些实用程序方法的实用程序类来发送电子邮件,然后将该实用程序方法用于不同的SMTP服务器。
JavaMail示例程序
我们的EmailUtil类只有一个发送电子邮件的方法,如下所示,它需要javax.mail.Session和一些其他必填字段作为参数。
为简单起见,一些参数是硬编码的,但是您可以扩展此方法以传递它们或者从某些配置文件中读取它。
package com.theitroad.mail; import java.io.UnsupportedEncodingException; import java.util.Date; import javax.activation.DataHandler; import javax.activation.DataSource; import javax.activation.FileDataSource; import javax.mail.BodyPart; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Multipart; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; public class EmailUtil { /** * Utility method to send simple HTML email * @param session * @param toEmail * @param subject * @param body */ public static void sendEmail(Session session, String toEmail, String subject, String body){ try { MimeMessage msg = new MimeMessage(session); //set message headers msg.addHeader("Content-type", "text/HTML; charset=UTF-8"); msg.addHeader("format", "flowed"); msg.addHeader("Content-Transfer-Encoding", "8bit"); msg.setFrom(new InternetAddress("[email protected]", "NoReply-JD")); msg.setReplyTo(InternetAddress.parse("[email protected]", false)); msg.setSubject(subject, "UTF-8"); msg.setText(body, "UTF-8"); msg.setSentDate(new Date()); msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toEmail, false)); System.out.println("Message is ready"); Transport.send(msg); System.out.println("EMail Sent Successfully!!"); } catch (Exception e) { e.printStackTrace(); } } }
请注意,我在MimeMessage中设置了一些标头属性,电子邮件客户端使用它们来正确呈现和显示电子邮件。
该程序的其余部分很简单并且容易理解。
现在,让我们创建程序以发送未经身份验证的电子邮件。
使用SMTP无需验证即可使用SMTP发送Java邮件
package com.theitroad.mail; import java.util.Properties; import javax.mail.Session; public class SimpleEmail { public static void main(String[] args) { System.out.println("SimpleEmail Start"); String smtpHostServer = "smtp.example.com"; String emailID = "[email protected]"; Properties props = System.getProperties(); props.put("mail.smtp.host", smtpHostServer); Session session = Session.getInstance(props, null); EmailUtil.sendEmail(session, emailID,"SimpleEmail Testing Subject", "SimpleEmail Testing Body"); } }
请注意,我正在使用Session.getInstance()通过传递Properties对象来获取Session对象。
我们需要使用SMTP服务器主机设置mail.smtp.host属性。
如果SMTP服务器不在默认端口(25)上运行,则还需要设置mail.smtp.port属性。
只需使用您的无身份验证SMTP服务器并通过将收件人电子邮件ID设置为您自己的电子邮件ID来运行该程序,您将很快收到该电子邮件。
该程序易于理解并且运行良好,但是在现实生活中,大多数SMTP服务器都使用某种身份验证,例如TLS或者SSL身份验证。
现在,我们将看到如何为这些身份验证协议创建Session对象。
使用TLS身份验证以Java SMTP发送电子邮件
package com.theitroad.mail; import java.util.Properties; import javax.mail.Authenticator; import javax.mail.PasswordAuthentication; import javax.mail.Session; public class TLSEmail { /** Outgoing Mail (SMTP) Server requires TLS or SSL: smtp.gmail.com (use authentication) Use Authentication: Yes Port for TLS/STARTTLS: 587 */ public static void main(String[] args) { final String fromEmail = "[email protected]"; //requires valid gmail id final String password = "mypassword"; //correct password for gmail id final String toEmail = "[email protected]"; //can be any email id System.out.println("TLSEmail Start"); Properties props = new Properties(); props.put("mail.smtp.host", "smtp.gmail.com"); //SMTP Host props.put("mail.smtp.port", "587"); //TLS Port props.put("mail.smtp.auth", "true"); //enable authentication props.put("mail.smtp.starttls.enable", "true"); //enable STARTTLS //create Authenticator object to pass in Session.getInstance argument Authenticator auth = new Authenticator() { //override the getPasswordAuthentication method protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(fromEmail, password); } }; Session session = Session.getInstance(props, auth); EmailUtil.sendEmail(session, toEmail,"TLSEmail Testing Subject", "TLSEmail Testing Body"); } }
由于我使用的是所有人都可以访问的GMail SMTP服务器,因此您可以在上述程序中设置正确的变量并自己运行。
具有SSL身份验证的Java SMTP示例
package com.theitroad.mail; import java.util.Properties; import javax.mail.Authenticator; import javax.mail.PasswordAuthentication; import javax.mail.Session; public class SSLEmail { /** Outgoing Mail (SMTP) Server requires TLS or SSL: smtp.gmail.com (use authentication) Use Authentication: Yes Port for SSL: 465 */ public static void main(String[] args) { final String fromEmail = "[email protected]"; //requires valid gmail id final String password = "mypassword"; //correct password for gmail id final String toEmail = "[email protected]"; //can be any email id System.out.println("SSLEmail Start"); Properties props = new Properties(); props.put("mail.smtp.host", "smtp.gmail.com"); //SMTP Host props.put("mail.smtp.socketFactory.port", "465"); //SSL Port props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); //SSL Factory Class props.put("mail.smtp.auth", "true"); //Enabling SMTP Authentication props.put("mail.smtp.port", "465"); //SMTP Port Authenticator auth = new Authenticator() { //override the getPasswordAuthentication method protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(fromEmail, password); } }; Session session = Session.getDefaultInstance(props, auth); System.out.println("Session created"); EmailUtil.sendEmail(session, toEmail,"SSLEmail Testing Subject", "SSLEmail Testing Body"); EmailUtil.sendAttachmentEmail(session, toEmail,"SSLEmail Testing Subject with Attachment", "SSLEmail Testing Body with Attachment"); EmailUtil.sendImageEmail(session, toEmail,"SSLEmail Testing Subject with Image", "SSLEmail Testing Body with Image"); } }
该程序与TLS身份验证几乎相同,只是某些属性不同。
如您所见,我正在从EmailUtil类调用一些其他方法来在电子邮件中发送附件和图像,但我尚未定义它们。
实际上,我让它们稍后显示,并在本教程开始时保持简单。
JavaMail示例–使用Java发送带有附件的邮件
要发送文件作为附件,我们需要创建一个对象javax.mail.internet.MimeBodyPart和javax.mail.internet.MimeMultipart。
首先在电子邮件中添加文本消息的正文部分,然后使用FileDataSource将文件附加到多部分正文的第二部分中。
该方法如下所示。
/** * Utility method to send email with attachment * @param session * @param toEmail * @param subject * @param body */ public static void sendAttachmentEmail(Session session, String toEmail, String subject, String body){ try{ MimeMessage msg = new MimeMessage(session); msg.addHeader("Content-type", "text/HTML; charset=UTF-8"); msg.addHeader("format", "flowed"); msg.addHeader("Content-Transfer-Encoding", "8bit"); msg.setFrom(new InternetAddress("[email protected]", "NoReply-JD")); msg.setReplyTo(InternetAddress.parse("[email protected]", false)); msg.setSubject(subject, "UTF-8"); msg.setSentDate(new Date()); msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toEmail, false)); //Create the message body part BodyPart messageBodyPart = new MimeBodyPart(); //Fill the message messageBodyPart.setText(body); //Create a multipart message for attachment Multipart multipart = new MimeMultipart(); //Set text message part multipart.addBodyPart(messageBodyPart); //Second part is attachment messageBodyPart = new MimeBodyPart(); String filename = "abc.txt"; DataSource source = new FileDataSource(filename); messageBodyPart.setDataHandler(new DataHandler(source)); messageBodyPart.setFileName(filename); multipart.addBodyPart(messageBodyPart); //Send the complete message parts msg.setContent(multipart); //Send message Transport.send(msg); System.out.println("EMail Sent Successfully with attachment!!"); }catch (MessagingException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } }
该程序乍一看可能看起来很复杂,但很简单,只需为短信创建一个正文部分,为附件创建另一个正文部分,然后将其添加到多部分中。
您也可以扩展此方法以附加多个文件。
JavaMail示例–使用Java发送带有图片的邮件
由于我们可以创建HTML正文消息,因此,如果图像文件位于某个服务器位置,则可以使用img元素在消息中显示它们。
但是有时我们想将图像附加到电子邮件中,然后在电子邮件正文中使用它。
您一定已经看过这么多带有图像附件的电子邮件,并且这些电子邮件也在电子邮件中使用。
诀窍是像其他任何附件一样附加图像文件,然后设置图像文件的Content-ID标头,然后在电子邮件正文中使用与<img src ='cid:image_id'>相同的内容ID。
/** * Utility method to send image in email body * @param session * @param toEmail * @param subject * @param body */ public static void sendImageEmail(Session session, String toEmail, String subject, String body){ try{ MimeMessage msg = new MimeMessage(session); msg.addHeader("Content-type", "text/HTML; charset=UTF-8"); msg.addHeader("format", "flowed"); msg.addHeader("Content-Transfer-Encoding", "8bit"); msg.setFrom(new InternetAddress("[email protected]", "NoReply-JD")); msg.setReplyTo(InternetAddress.parse("[email protected]", false)); msg.setSubject(subject, "UTF-8"); msg.setSentDate(new Date()); msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toEmail, false)); //Create the message body part BodyPart messageBodyPart = new MimeBodyPart(); messageBodyPart.setText(body); //Create a multipart message for attachment Multipart multipart = new MimeMultipart(); //Set text message part multipart.addBodyPart(messageBodyPart); //Second part is image attachment messageBodyPart = new MimeBodyPart(); String filename = "image.png"; DataSource source = new FileDataSource(filename); messageBodyPart.setDataHandler(new DataHandler(source)); messageBodyPart.setFileName(filename); //Trick is to add the content-id header here messageBodyPart.setHeader("Content-ID", "image_id"); multipart.addBodyPart(messageBodyPart); //third part for displaying image in the email body messageBodyPart = new MimeBodyPart(); messageBodyPart.setContent("<h1>Attached Image</h1>" + "<img src='cid:image_id'>", "text/html"); multipart.addBodyPart(messageBodyPart); //Set the multipart message to the email message msg.setContent(multipart); //Send message Transport.send(msg); System.out.println("EMail Sent Successfully with image!!"); }catch (MessagingException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } }
JavaMail API故障排除技巧
当您的系统无法解析SMTP服务器的IP地址时,可能会出现java.net.UnknownHostException异常,这可能是错误的或者无法从网络访问。
例如,GMail SMTP服务器是smtp.gmail.com,如果我使用smtp.google.com,则会收到此异常。
如果主机名正确,请尝试通过命令行ping服务器,以确保可以从系统访问该服务器。如果您的程序停留在Transport send()方法调用中,请检查SMTP端口是否正确。
如果正确,请使用telnet验证它是否可以从您的计算机访问,您将获得如下所示的输出。