Java + 騰訊企業郵箱 + javamail + SSL 發送郵件

說實話騰訊的企業郵箱真心不錯!css

騰訊企業郵箱官網:http://exmail.qq.com/login/html

新用戶註冊:http://exmail.qq.com/onlinesell/introjava

 

點擊開通git

你跟着步驟走就好了,沒啥難的,若是你沒有域名,你就去買一個唄,也花不了多少錢的。github

註冊成功後,是這個頁面,而且會有一個彈窗告訴你一些信息spring

如今你點擊添加成員,由於你不添加成員的話你是沒法發送郵件的。安全

完成後是這樣服務器

而後你打開騰訊企業郵箱登陸界面,輸入你剛纔增長的成員郵箱的:登陸名 + 密碼,進去後是一個相似於普通QQ郵箱的界面微信

 

到這裏郵箱部分就解決了,哦還有,騰訊會自動給你發一個郵件,session

點開後是這個,

之前寫過普通QQ郵箱的發送代碼,我從沒見過SSL,因此一開始全然不懂。。,可是上網查閱得知

隨着各個Mail服務器對於安全的重視,紛紛採用基於SSL的Mail登錄方式進行發送和接收電子郵件

好了如今開始寫代碼。

你們反映以前寫的容易誤導人,因此今天修改了這個文章一下2017-09-05

 有一個屬性文件用來存儲郵箱信息的

email.properties,放在src路徑下面
e.account=帳戶名
e.pass=密碼
e.host=smtp.exmail.qq.com
e.port=465
e.protocol=smtp

 

下面是發送類:

package mail.demo;

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;

import org.springframework.core.io.support.PropertiesLoaderUtils;

import com.sun.mail.util.MailSSLSocketFactory;

public class SendEmailUtil {

    private static String account;    //登陸用戶名
    private static String pass;        //登陸密碼
    private static String host;        //服務器地址(郵件服務器)
    private static String port;        //端口
    private static String protocol; //協議
    
    static{
        Properties prop = new Properties();
//        InputStream instream = ClassLoader.getSystemResourceAsStream("email.properties");//測試環境
        try {
//            prop.load(instream);//測試環境
            prop = PropertiesLoaderUtils.loadAllProperties("email.properties");//生產環境
        } catch (IOException e) {
            System.out.println("加載屬性文件失敗");
        }
        account = prop.getProperty("e.account");
        pass = prop.getProperty("e.pass");
        host = prop.getProperty("e.host");
        port = prop.getProperty("e.port");
        protocol = prop.getProperty("e.protocol");
    }
    
    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);  
        }  
    }
    
    private String to;    //收件人
    private String subject;    //主題
    private String content;    //內容
    private String fileStr;    //附件路徑

    public SendEmailUtil(String to, String subject, String content, String fileStr) {
        this.to = to;
        this.subject = subject;
        this.content = content;
        this.fileStr = fileStr;
    }



    public void send(){
        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 sf = null;
        try {
            sf = new MailSSLSocketFactory();
            sf.setTrustAllHosts(true);
        } catch (GeneralSecurityException e1) {
            e1.printStackTrace();
        }
        prop.put("mail.smtp.ssl.enable", "true");
        prop.put("mail.smtp.ssl.socketFactory", sf);
        
        Session session = Session.getDefaultInstance(prop, new MyAuthenricator(account, pass));
        session.setDebug(true);
        MimeMessage mimeMessage = new MimeMessage(session);
        try {
            //發件人
            mimeMessage.setFrom(new InternetAddress(account,"XXX"));        //能夠設置發件人的別名
            //mimeMessage.setFrom(new InternetAddress(account));    //若是不須要就省略
            //收件人
            mimeMessage.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
            //主題
            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);
            
            //添加圖片&附件
            body = new MimeBodyPart();
            body.attachFile(fileStr);
            mp.addBodyPart(body);
            
            //設置郵件內容
            mimeMessage.setContent(mp);
            //僅僅發送文本
            //mimeMessage.setText(content);
            mimeMessage.saveChanges();
            Transport.send(mimeMessage);
        } catch (MessagingException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    

}

 

考慮到實際中要保證吞吐量,我寫了一個線程:

package mail.demo;

public class Sending implements Runnable{

    private String to;    //收件人
    private String subject;    //主題
    private String content;    //內容
    private String fileStr;    //附件路徑

    public Sending(String to, String subject, String content, String fileStr) {
        this.to = to;
        this.subject = subject;
        this.content = content;
        this.fileStr = fileStr;
    }

    @Override
    public void run() {
        SendEmailUtil sendEmail = new SendEmailUtil(to, subject, content, fileStr);
        sendEmail.send();
    }

}

 

線程的創建銷燬開銷也是很大的,我建了一個線程池,若是遇到批量處理的話能夠好用一些。

package mail.demo;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 單例,線程池
 * @author Taozi
 *
 */
public class SendingPool {
    
    private SendingPool() {
    }
    private static class Inner{
        private static SendingPool instance = new SendingPool();
    }
    
    public static SendingPool getInstance(){
        return Inner.instance;
    }
    
    private static int nThreads = 10;
    private static ExecutorService executor = Executors.newFixedThreadPool(nThreads);
    
    public SendingPool addThread(Sending sending){
        executor.execute(sending);
        return getInstance();
    }
    
    public void shutDown(){
        executor.shutdown();
    }
}

 

 下面是測試類

package mail.demo;

public class MyTest {

    public static void main(String[] args) {
        SendingPool pool = SendingPool.getInstance();
        
        pool.addThread(new Sending("收件人", "AAA", createEmail().toString(), "file/1.jpg")).shutDown();
        
    }
    
    private static StringBuilder createEmail() {
        StringBuilder emailContent = new StringBuilder("<!DOCTYPE html><html><head><meta charset='UTF-8'><title>快來買桃子</title><style type='text/css'>        .container{            font-family: 'Microsoft YaHei';            width: 600px;            margin: 0 auto;            padding: 8px;            border: 3px dashed #db303f;            border-radius: 6px;        }        .title{            text-align: center;            color: #db303f;        }        .content{            text-align: justify;            color: #717273;            font-weight: 600;        }        footer{            text-align: right;            color: #db303f;            font-weight: 600;            font-size: 18px;        }</style></head><body><div class='container'><h2 class='title'>好吃的桃子</h2><p class='content'>桃子含有維生素A、維生素B和維生素C,兒童多吃桃子可以使身體健康成長,由於桃子含有的多種維生索能夠直接強化他們的身體和智力。</p><footer>聯繫桃子:11110000</footer></div></body></html>");
        return emailContent;
    }
}

 提示:實際中不要調用shutDown方法,由於這個是優雅關閉線程池的,若是你關閉了再次調用是會出問題的喲

 提示2:若是你不須要附件的功能,請把附件相關的代碼註釋,或者加個判斷

//添加圖片&附件
if(fileStr != null){
    body = new MimeBodyPart();
    body.attachFile(fileStr);
    mp.addBodyPart(body);
}

 

 下面是我收到的郵件,Html正文+附件

 到此就完成了

 完整代碼去GitHub下載,Javamail

 2019-07-29更新http://www.javashuo.com/article/p-yjchpxsp-gx.html

小夥伴們在使用過程當中遇到各類各樣的問題,在下一一列舉。

=============================================================================================

錯誤1:

 javax.mail.AuthenticationFailedException: 535 Error: authentication failed, system busy
 
身份驗證失敗,大多數都是這個問題。一種說法是帳戶密碼不是登陸密碼,而是「 受權碼」;另一種是「 客戶端專用密碼

關於客戶端專用密碼 。

若是說您綁定了微信,就不能繼續使用登陸密碼了,取代的是「客戶端專用密碼

 這裏借用一下熱心網友的截圖,如下是綁定微信後的安全設置:登陸方式和專用密碼。

若是你開啓了這些東西,那麼在使用Javamail的時候,密碼就要用生成的「專用密碼

 

關於「受權碼

我想說:「不存在的」,若是你用的是企業郵,那麼就不須要這個東西吧,你用我的的才須要(純屬猜想,本人也沒用過)

 關於發信量

有的小夥伴跟我說發了必定數量就不行了,我特意去查了查,原來這裏是個坑對於頻繁發送的場景十分不利),截圖以下:

因此,我建議想要無限頻繁發送,那就去別的提供商看看,或者本身搭建郵件服務器

相關文章
相關標籤/搜索