很多應用都會涉及到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="[email protected]"></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);