很多应用都会涉及到email,但自己架设email服务器的情况还是很少的。一般都是直接借用一些门户网站的邮件服务发邮件。
实现方式一般有如下3种方案:原始级别—自己直接写socket,处理通讯协议;
简单级别—自行封装mail.jar的API;
开源封装级别—引入一些开源框架的封装,功能强大,却又简单易用。
下面粗略介绍一下以上三种方式的实现情况。
1.
原始级别
邮件格式 + SMTP协议 +
自己写socket
由于直接处理协议层面的数据,需要开发者熟悉协议(否则,起码也需要边开发,边对着rfc文档),以及面对一堆的数据封装,异常处理等细节。
其实好处也在于此。所有的细节都是对开发者开放的,你觉得有多好就多好。
SMTP协议:参考rfc5321
邮件格式:参考rfc2882
Socket代码
Socket client = new Socket (SMTPServerAddress, SMTPPort);
// …. Socket read/ write
参考协议格式,处理通讯数据
2.
简单级别
引入mail.jar包
Mail.java 包对通讯协议做了封装,但在具体应用层面,还是有不少邮件的细节需要用户处理。
实现例子:
//服务器信息
Properties props = new Properties();
props.put("mail.smtp.host",
_hostName);
props.put("mail.smtp.auth",
_needAuth.toString());
//验证
Authenticator authenticator =
null;
if(_needAuth){
authenticator =
new Authenticator() {
@Override
public PasswordAuthentication getPasswordAuthentication() {
returnnew PasswordAuthentication(_authUser,
_authPwd);
}
};
}
//处理邮件信息
Session session = Session.getInstance(props, authenticator);
Message msg = new MimeMessage(session);
if (isNeedNotification()) {
msg.setHeader("Disposition-Notification-To",
"1");
}
msg.setSentDate(new Date());
if(_subject!=null){
msg.setSubject( MimeUtility.encodeText(_subject, getEncoding(),"B"));
}
String authEmail = getAuthEmail(getAuthUser(), getHostName());
msg.setFrom(new InternetAddress(authEmail, getPersonalName(), getEncoding()));
msg.setRecipients(Message.RecipientType.TO, getInternetAddress(_toList));
if(_ccList!=null){
msg.setRecipients(Message.RecipientType.CC, getInternetAddress(_ccList));
}
if(_bccList!=null){
msg.setRecipients(Message.RecipientType.BCC, getInternetAddress(_bccList));
}
if(_attachFiles!=null
&& _attachFiles.length > 0){
MimeMultipart mimeMultipart =
new MimeMultipart();
//body
MimeBodyPart mimeBodyPart =
new MimeBodyPart();
// mimeBodyPart.setText(getMessage(), getEncoding());
mimeBodyPart.setContent(getMessage(), getContentType() +
";charset="+getEncoding());
mimeMultipart.setSubType("related");
mimeMultipart.addBodyPart(mimeBodyPart);
//attachments
for (int i=0; i<_attachFiles.length;
i++) {
FileDataSource filedatasource =
new FileDataSource(_attachFiles[i]);
DataHandler dataHandler =
new DataHandler(filedatasource);
MimeBodyPart attachmentPart =
new MimeBodyPart();
attachmentPart.setDataHandler(dataHandler);
attachmentPart.setFileName(MimeUtility.encodeText(filedatasource.getName(), getEncoding(),
"B"));
attachmentPart.setHeader("Content-ID", filedatasource.getName());
mimeMultipart.addBodyPart(attachmentPart);
}
msg.setContent(mimeMultipart);
}else{
// msg.setContent(_message, "text/plain;charset=" + getEncoding());
msg.setContent(_message, getContentType() +
";charset="+getEncoding());
}
Transport.send(msg);
3.
开源封装级别
邮件模版 +
系统邮件请求 + 开源Email API
封装类
简单易用且功能强大,开发者的关注已经很大程度上转到了邮件内容本身。
例如,使用velocity + spring
3.1
模版
<body>
<div id="wrapper" >
<h1>${domain}</h1>
<h2>Hi, ${email}!</h2>
<p>欢迎使用 xxx 系统</p>
<p>请点击以下按钮完成注册激活(72小时内有效)</p>
<p><a target="_blank" class="button" href="http://www.xxx.com/...activation?id=${id}">激活</a></p>
<p>或者将以下链接复制到浏览器地址栏进入到激活页面:</p>
</div>
</body>
3.2
生成邮件内容
把邮件请求中的参数替换掉模块中的参数,生成邮件内容。
例如 :
velocityEngine.mergeTemplate(location, TEMPLATE_ENCODE, context, writer)
3.3 spring 配置
引入spring框架
org.springframework.mail.javamail.JavaMailSenderImpl.java
<bean
id="mailSender"
class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property
name="host"
value="mail.xxx.com"/>
<property
name="username"
value="noreply@xxx.com"></property>
<property
name="password"
value="xxxxxxx"></property>
<property
name="javaMailProperties">
<props>
<prop
key="mail.smtp.auth">true</prop>
<prop
key="mail.smtp.timeout">25000</prop>
</props>
</property>
</bean>
3.4 发邮件
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper
helper = new MimeMessageHelper(message,
MAIL_ENCODE);
helper.setTo(targetAddress);
helper.setFrom("sender");
helper.setSubject(template.getTitle());
// helper.setText(VelocityEngineUtils.mergeTemplateIntoString(velocityEngine, getTemplateLocation(path, templateCode), MAIL_ENCODE,
args), true);
helper.setText(velocityManager.parseTemplate(getTemplateLocation(path, templateCode), args),
true);