用程序發郵件首先需要一個smtp服務器,
雖然說網上也有自建服務器的教程,但是由於工程量大,
還要兼容各大郵箱廠商,有可能發送失敗或被歸爲垃圾郵件。
所以不推薦自建smtp服務器實現。
推薦是有2種方法來實現 第三方郵箱發郵件
1、買類似阿里雲的smtp資源包(阿里雲 1000條 / 2元)
2、申請一個騰訊、網易163的郵箱,開通smtp服務端口,藉由他們的服務器來轉發。
(其中部分第三方郵箱可以實現用自己的域名來接發郵件,例如[email protected])
本文中介紹的是第二種方法,用騰訊企業郵箱爲例
參考借鑑的大神的原文地址:https://www.cnblogs.com/LUA123/p/5575134.html
這裏重點只說明一下,騰訊企業郵箱 + javamail 來實現發郵件,代碼的部分。
其他郵箱,例如個人的qq郵箱 163郵箱也可以用這個方法實現,申請和設置方法借鑑百度吧
補充一下!騰訊企業郵箱和qq郵箱方法有幾個不同,我在末尾加了qq郵箱的方案
正文開始
先說騰訊企業郵箱
maven
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.7</version>
</dependency>
另外我用到了一個 StringUtils.isNotBlank() 方法 可以選擇引入以下maven依賴,也可以改寫成 xxx != null && !"".equals(xxx) 等價的代碼
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
</dependency>
java 工具類
需要把 用戶名、密碼、發件人別名 等參數填成你自己申請的
package com.gemini.common.utils;
import com.sun.mail.util.MailSSLSocketFactory;
import org.apache.commons.lang.StringUtils;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.util.Date;
import java.util.Properties;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
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 EmailUtils {
// 騰訊企業郵箱 也可以換成別家的
private static final String protocol = "smtp";// 協議
private static final String host = "smtp.exmail.qq.com";// 地址
private static final String port = "465";// 端口
private static final String account = "用戶名";// 用戶名
private static final String pass = "密碼";// 密碼
private static final String personal = "發件人別名(選填)";// 發件人別名,不需要設爲空串或null
// 權限認證
static class MyAuthenricator extends Authenticator {
String u = null;
String p = null;
public MyAuthenricator(String u, String p) {
this.u = u;
this.p = p;
}
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(u, p);
}
}
/**
* 發送郵件工具方法
*
* @param recipients 收件人
* @param subject 主題
* @param content 內容
* @param fileStr 附件路徑
* @return true/false 發送成功
*/
public static boolean sendEmail(String recipients, String subject, String content, String fileStr) {
Properties prop = new Properties();
//協議
prop.setProperty("mail.transport.protocol", protocol);
//服務器
prop.setProperty("mail.smtp.host", host);
//端口
prop.setProperty("mail.smtp.port", port);
//使用smtp身份驗證
prop.setProperty("mail.smtp.auth", "true");
//使用SSL,企業郵箱必需!
//開啓安全協議
MailSSLSocketFactory mailSSLSocketFactory = null;
try {
mailSSLSocketFactory = new MailSSLSocketFactory();
mailSSLSocketFactory.setTrustAllHosts(true);
} catch (GeneralSecurityException e1) {
e1.printStackTrace();
}
prop.put("mail.smtp.ssl.enable", "true");
prop.put("mail.smtp.ssl.socketFactory", mailSSLSocketFactory);
Session session = Session.getDefaultInstance(prop, new MyAuthenricator(account, pass));
session.setDebug(true);
MimeMessage mimeMessage = new MimeMessage(session);
try {
//發件人
if (StringUtils.isNotBlank(personal))
mimeMessage.setFrom(new InternetAddress(account, personal));//可以設置發件人的別名
else
mimeMessage.setFrom(new InternetAddress(account));//如果不需要就省略
//收件人
mimeMessage.addRecipient(Message.RecipientType.TO, new InternetAddress(recipients));
//主題
mimeMessage.setSubject(subject);
//時間
mimeMessage.setSentDate(new Date());
//容器類,可以包含多個MimeBodyPart對象
Multipart mp = new MimeMultipart();
//MimeBodyPart可以包裝文本,圖片,附件
MimeBodyPart body = new MimeBodyPart();
//HTML正文
body.setContent(content, "text/html; charset=UTF-8");
mp.addBodyPart(body);
//添加圖片&附件
if(StringUtils.isNotBlank(fileStr)){
body = new MimeBodyPart();
body.attachFile(fileStr);
mp.addBodyPart(body);
}
//設置郵件內容
mimeMessage.setContent(mp);
//僅僅發送文本
//mimeMessage.setText(content);
mimeMessage.saveChanges();
Transport.send(mimeMessage);
// 發送成功
return true;
} catch (MessagingException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
public static void main(String[] args) {
sendEmail("你的郵箱地址","test","test",null);
}
}
關於上述方案,適用於一般的郵箱申請(騰訊企業郵箱、網易郵箱),但不適用於qq郵箱,原因是qq郵箱目前只接受授權碼方案登錄,官方的解釋是“溫馨提示:在第三方登錄QQ郵箱,可能存在郵件泄露風險,甚至危害Apple ID安全,建議使用QQ郵箱手機版登錄。 繼續獲取授權碼登錄第三方客戶端郵箱 。”
使用上述方法登錄qq郵箱會遇到報錯
javax.mail.AuthenticationFailedException: 535 Error: ÇëʹÓÃÊÚȨÂëµÇ¼¡£ÏêÇéÇë¿´: http://service.mail.qq.com/cgi-bin/help?subtype=1&&id=28&&no=1001256
如圖
意思就是不支持直接用默認密碼登錄,必須去申請一個授權碼作爲密碼登錄
其實流程和工具類都一樣就重點說 2個不一樣的地方
1、密碼不是你的郵箱密碼了,而是授權碼。
獲取方式 [登錄郵箱] - [設置] - [賬戶] ,然後如下圖找到POP3/SMTP服務的下面,有一句溫馨提示 先點 [生成授權碼] ,再根據提示獲取到授權碼。
授權碼就是javamail裏的password
2、host不同
騰訊企業郵箱的host是
private static final String host = "smtp.exmail.qq.com";// 地址
普通qq郵箱的host是
private static final String host = "smtp.qq.com";// 地址
修改這兩個地方即可適用於個人普通的qq郵箱
最終效果如下
另外本文也發佈在了我的個人博客: https://zzzmh.cn/single?id=49