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


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

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

新用戶注冊:http://exmail.qq.com/onlinesell/intro

 

點擊開通

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

注冊成功后,是這個頁面,並且會有一個彈窗告訴你一些信息

現在你點擊添加成員,因為你不添加成員的話你是無法發送郵件的。

完成后是這樣

然后你打開騰訊企業郵箱登錄界面,輸入你剛才增加的成員郵箱的:登錄名 + 密碼,進去后是一個類似於普通QQ郵箱的界面

 

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

點開后是這個,

以前寫過普通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更新https://www.cnblogs.com/LUA123/p/11265995.html

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

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

錯誤1:

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

關於客戶端專用密碼 。

如果說您綁定了微信,就不能繼續使用登錄密碼了,取代的是“客戶端專用密碼

 這里借用一下熱心網友的截圖,以下是綁定微信后的安全設置:登錄方式和專用密碼。

如果你開啟了這些東西,那么在使用Javamail的時候,密碼就要用生成的“專用密碼

 

關於“授權碼

我想說:“不存在的”,如果你用的是企業郵,那么就不需要這個東西吧,你用個人的才需要(純屬猜測,本人也沒用過)

 關於發信量

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

所以,我建議想要無限頻繁發送,那就去別的提供商看看,或者自己搭建郵件服務器

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM