用程序发邮件首先需要一个smtp服务器,

虽然说网上也有自建服务器的教程,但是由于工程量大,

还要兼容各大邮箱厂商,有可能发送失败或被归为垃圾邮件。

所以不推荐自建smtp服务器实现。

 

推荐是有2种方法来实现 第三方邮箱发邮件

1、买类似阿里云的smtp资源包(阿里云 1000条 / 2元)

2、申请一个腾讯、网易163的邮箱,开通smtp服务端口,借由他们的服务器来转发。

(其中部分第三方邮箱可以实现用自己的域名来接发邮件,例如service@baidu.com)

本文中介绍的是第二种方法,用腾讯企业邮箱为例


参考借鉴的大神的原文地址:https://www.cnblogs.com/LUA123/p/5575134.html

这里重点只说明一下,腾讯企业邮箱 + javamail 来实现发邮件,代码的部分。

其他邮箱,例如个人的qq邮箱 163邮箱也可以用这个方法实现,申请和设置方法借鉴百度吧

补充一下!腾讯企业邮箱和qq邮箱方法有几个不同,我在末尾加了qq邮箱的方案

 

正文开始

先说腾讯企业邮箱

maven

  1. <dependency>
  2.     <groupId>javax.mail</groupId>
  3.     <artifactId>mail</artifactId>
  4.     <version>1.4.7</version>
  5. </dependency>

 

另外我用到了一个 StringUtils.isNotBlank() 方法 可以选择引入以下maven依赖,也可以改写成 xxx != null && !"".equals(xxx) 等价的代码

  1. <dependency>
  2.     <groupId>org.apache.commons</groupId>
  3.     <artifactId>commons-lang3</artifactId>
  4.     <version>3.7</version>
  5. </dependency>

 

java 工具类

需要把 用户名、密码、发件人别名 等参数填成你自己申请的

  1. package com.gemini.common.utils;
  2.  
  3.  
  4. import com.sun.mail.util.MailSSLSocketFactory;
  5. import org.apache.commons.lang.StringUtils;
  6.  
  7. import java.io.IOException;
  8. import java.io.UnsupportedEncodingException;
  9. import java.security.GeneralSecurityException;
  10. import java.util.Date;
  11. import java.util.Properties;
  12.  
  13. import javax.mail.Authenticator;
  14. import javax.mail.Message;
  15. import javax.mail.MessagingException;
  16. import javax.mail.Multipart;
  17. import javax.mail.PasswordAuthentication;
  18. import javax.mail.Session;
  19. import javax.mail.Transport;
  20. import javax.mail.internet.InternetAddress;
  21. import javax.mail.internet.MimeBodyPart;
  22. import javax.mail.internet.MimeMessage;
  23. import javax.mail.internet.MimeMultipart;
  24.  
  25. public class EmailUtils {
  26.  
  27.     // 腾讯企业邮箱 也可以换成别家的
  28.     private static final String protocol = "smtp";// 协议
  29.     private static final String host = "smtp.exmail.qq.com";// 地址
  30.     private static final String port = "465";// 端口
  31.     private static final String account = "用户名";// 用户名
  32.     private static final String pass = "密码";// 密码
  33.     private static final String personal = "发件人别名(选填)";// 发件人别名,不需要设为空串或null
  34.  
  35.     // 权限认证
  36.     static class MyAuthenricator extends Authenticator {
  37.         String u = null;
  38.         String p = null;
  39.  
  40.         public MyAuthenricator(String u, String p) {
  41.             this.= u;
  42.             this.= p;
  43.         }
  44.         @Override
  45.         protected PasswordAuthentication getPasswordAuthentication() {
  46.             return new PasswordAuthentication(u, p);
  47.         }
  48.     }
  49.  
  50.     /**
  51.      * 发送邮件工具方法
  52.      *
  53.      * @param recipients 收件人
  54.      * @param subject    主题
  55.      * @param content    内容
  56.      * @param fileStr    附件路径
  57.      * @return true/false 发送成功
  58.      */
  59.     public static boolean sendEmail(String recipients, String subject, String content, String fileStr) {
  60.         Properties prop = new Properties();
  61.         //协议
  62.         prop.setProperty("mail.transport.protocol", protocol);
  63.         //服务器
  64.         prop.setProperty("mail.smtp.host", host);
  65.         //端口
  66.         prop.setProperty("mail.smtp.port", port);
  67.         //使用smtp身份验证
  68.         prop.setProperty("mail.smtp.auth", "true");
  69.         //使用SSL,企业邮箱必需!
  70.         //开启安全协议
  71.         MailSSLSocketFactory mailSSLSocketFactory = null;
  72.         try {
  73.             mailSSLSocketFactory = new MailSSLSocketFactory();
  74.             mailSSLSocketFactory.setTrustAllHosts(true);
  75.         } catch (GeneralSecurityException e1) {
  76.             e1.printStackTrace();
  77.         }
  78.         prop.put("mail.smtp.ssl.enable", "true");
  79.         prop.put("mail.smtp.ssl.socketFactory", mailSSLSocketFactory);
  80.  
  81.         Session session = Session.getDefaultInstance(prop, new MyAuthenricator(account, pass));
  82.         session.setDebug(true);
  83.         MimeMessage mimeMessage = new MimeMessage(session);
  84.         try {
  85.             //发件人
  86.             if (StringUtils.isNotBlank(personal))
  87.                 mimeMessage.setFrom(new InternetAddress(account, personal));//可以设置发件人的别名
  88.             else
  89.                 mimeMessage.setFrom(new InternetAddress(account));//如果不需要就省略
  90.             //收件人
  91.             mimeMessage.addRecipient(Message.RecipientType.TO, new InternetAddress(recipients));
  92.             //主题
  93.             mimeMessage.setSubject(subject);
  94.             //时间
  95.             mimeMessage.setSentDate(new Date());
  96.             //容器类,可以包含多个MimeBodyPart对象
  97.             Multipart mp = new MimeMultipart();
  98.  
  99.             //MimeBodyPart可以包装文本,图片,附件
  100.             MimeBodyPart body = new MimeBodyPart();
  101.             //HTML正文
  102.             body.setContent(content, "text/html; charset=UTF-8");
  103.             mp.addBodyPart(body);
  104.  
  105.             //添加图片&附件
  106.             if(StringUtils.isNotBlank(fileStr)){
  107.                 body = new MimeBodyPart();
  108.                 body.attachFile(fileStr);
  109.                 mp.addBodyPart(body);
  110.             }
  111.  
  112.             //设置邮件内容
  113.             mimeMessage.setContent(mp);
  114.             //仅仅发送文本
  115.             //mimeMessage.setText(content);
  116.             mimeMessage.saveChanges();
  117.             Transport.send(mimeMessage);
  118.             // 发送成功
  119.             return true;
  120.         } catch (MessagingException e) {
  121.             e.printStackTrace();
  122.         } catch (UnsupportedEncodingException e) {
  123.             e.printStackTrace();
  124.         } catch (IOException e) {
  125.             e.printStackTrace();
  126.         }
  127.         return false;
  128.     }
  129.  
  130.     public static void main(String[] args) {
  131.         sendEmail("你的邮箱地址","test","test",null);
  132.     }
  133. }

 


关于上述方案,适用于一般的邮箱申请(腾讯企业邮箱、网易邮箱),但不适用于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是

  1. private static final String host = "smtp.exmail.qq.com";// 地址

普通qq邮箱的host是

  1. private static final String host = "smtp.qq.com";// 地址



修改这两个地方即可适用于个人普通的qq邮箱








最终效果如下