您的位置:首页 > 编程语言 > Java开发

Java-mail发送邮件

2020-02-05 00:39 405 查看

1、调用工具类发射邮件*

@SuppressWarnings(“null”)
private void getSendEmailStartus(RequestInfo requestInfo) throws Exception {
String account = xxxxx;// 登录账户
String password =xxxxxxx;// 登录密码
// 抄送者账号
String csz = xxxxx;
String requestid = requestInfo.getRequestid();
FormtableMain19 find = DB.conn().find(FormtableMain19.class, “REQUESTID=?”, requestid);
// 附件名称
String[] fileName = null;
// 附件地址
String[] fileSrc = null;
if (null != find) {
String[] fjsc = new String[] { “123456C1”, “123456C2”, “123456C3” };
if (fjsc.length > 0) {
fileSrc = new String[fjsc.length];
fileName = new String[fjsc.length];
for (int i = 0; i < fjsc.length; i++) {
EmailPDF find2 = DB.conn().find(EmailPDF.class, “fileuniqueidentifier=?”, fjsc[i]);
fileName[i] = find2.getImagefilename();
fileSrc[i] = find2.getFilerealpath();
}
}
if (CustomUtil.isBlank(find.getYjll())) {
throw new RuntimeException(“邮件内容不能为空,requestId为:” + requestid);
}
if (CustomUtil.isBlank(find.getYxdz())) {
throw new RuntimeException(“邮件地址不能为空 ,requestId为:” + requestid);
}
if (!SendEmailUtil.isMailAddr(find.getYxdz())) {
throw new RuntimeException(“邮箱地址输入不合法 ,requestId为:” + requestid);
}
new SendEmailUtil().send(account, “xxx:” + find.getXm(), find.getYjll(), find.getYxdz() + “,” + csz,
fileSrc, account, password, fileName);
}

}

配置文件*

#邮箱服务配置
email.host = xxxxx.xxx.163.com #域民
email.prot = *** #端口
email.protocol = imap #协议
#邮箱账户、密码
devEmail.ACCOUNT = ************
devEmail.PWSSWORD = *************

邮件工具类*

private static Logger logger = Logger.getLogger(SendEmailUtil.class);
private static byte[] ZIP_HEADER_1 = new byte[] { 80, 75, 3, 4 };
private static byte[] ZIP_HEADER_2 = new byte[] { 80, 75, 5, 6 };
static {
System.setProperty(“mail.mime.splitlongparameters”, “false”);
System.setProperty(“mail.mime.charset”, “UTF-8”);
}

public static Session initProperties(String account, String password) {
Properties properties = new Properties();
properties.setProperty("mail.transport.protocol", PropUtil.getStringCK("ecustom", "email.protocol"));
properties.setProperty("mail.smtp.host", PropUtil.getStringCK("ecustom", "email.host"));
properties.setProperty("mail.smtp.port", PropUtil.getStringCK("ecustom", "email.prot"));
properties.put("mail.smtp.auth", "true");
MailSSLSocketFactory mailSSLSocketFactory = null;
try {
mailSSLSocketFactory = new MailSSLSocketFactory();
mailSSLSocketFactory.setTrustAllHosts(true);
} catch (GeneralSecurityException e) {
e.printStackTrace();
}properties.put("mail.smtp.enable", "true");
properties.put("mail.smtp.ssl.socketFactory", mailSSLSocketFactory);
properties.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
properties.put("mail.smtp.socketFactory.fallback", "false");
properties.put("mail.smtp.socketFactory.port", PropUtil.getStringCK("ecustom", "email.prot"));
存在session问题:
Session session = Session.getDefaultInstance(properties, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(account, password);
}});
第二种:
Session session = Session.getInstance(properties, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(account, password);
}});
session.setDebug(true);
return session;
}

拓展知识:

问题解决,
将 Session session = Session.getDefaultInstance(props, myauth);
改成
Session session = Session.getInstance(props, myauth);
即可
我就按照他的方法把代码里的方法替换了一下,重新运行,输入第一个邮箱账号和密码,成功发送,第二次输入其他的邮箱账号和密码,点发送,ok,成功了。
好了,到这里问题也解决了,但是还不明白Session.getDefaultInstance和 Session.getInstance有什么区别呢?又找了一下资料,结果找到了也是遇到过553异常的人写的一篇blog,他的blog标题居然是:
”JavaMail中Session.getDefaultInstance的应用“,
不是吧,这样太难找了,一般都是搜索问题名称,谁会搜索这个。如果发帖者能把标题改成问题,那我也就不用找这么就了。不过还是要感谢这个人,他在这篇帖子里详细的说明了为什么用Session.getDefaultInstance方法会出现在第二次输入其他邮箱账号登录时出现553异常。
以下内容都这摘自这个帖子:
http://muder2007.blog.163.com/blog/static/45933070200872025130613/

何谓getDefaultInstance?
从处理流程中可以看出,首先是从缓存中查找是否有properties存在
如果存在,则加载默认的properties
如果不存在才加载用户自己定义的properties,
所以当一个应用为每个用户独立创建properties的时候,还是应该调用getInstance,
除非你希望有一个默认的properties让用户使用

问题找到了,因为它会首先去内存和系统文件中去找properties,所以不管我在页面改几次数据,其实在后台中生成session时都和系统启动时的一样,所以在MailUtil.sendTextMessage(mailSession,RptTaskMailConfig.Sender,
receiver,null,mail_subject,mail_content,“GB2312”,null);时session里的sender和传入的sender不一致,因此出错,修改Session.getDefaultInstance(props, authentic);为Session.getInstance(props, authentic);后,可以正确发送修改帐号,密码等资料后的邮件.OK

最后再补充一下,session.getdefaultinstance和getinstance的区别 :

如果想要同时使用两个帐号发送javamail,比如使用1@a.com发送1#邮件,使用2@a.com发送2#邮件,这时候,你就需要同时创建两个java.mail.Session对象。但是如果你仍然使用Session.getDefaultInstance创建session对象的话,你会发现,第二个username:2@a.com创建的session永远都和第一个一样,这是为什么呢?因为,getDefaultInstance是真正单例模式,而且,里面的username和password属性是final型的,无法更改。所以,你会发现两封email都是由1@a.com发出来的。所以这个时候你要使用javax.mail.Session.getInstance()方法来创建session对象。

/**
* @Description: 发送邮件
* @Title: send
* @date 2019-10-08 17:12
* @param @param sender发件人别名
* @param @param subject邮件主题
* @param @param content接收者列表,多个接收者之间用","隔开
* @param @param receiverList :内容
* @param @param fileSrc []附件地址
* @return void 返回类型 fileName:[]附件名称 account: 发送者账户 password :发送者密码
* @throws @return void
* @param sender
* @param subject
* @param content
* @param receiverList
* @param fileSrc
* @throws Exception
*/
public void send(String sender, String subject, String content, String receiverList, String[] fileSrc,
String account, String password, String[] fileName) throws Exception {

Session session = initProperties(account, password);
MimeMessage mimeMessage = new MimeMessage(session);
mimeMessage.setFrom(new InternetAddress(account, sender));// 发件人,可以设置发件人的别名
InternetAddress[] internetAddressTo = new InternetAddress().parse(receiverList);
mimeMessage.setRecipients(Message.RecipientType.TO, internetAddressTo);
mimeMessage.setSubject(subject);
mimeMessage.setSentDate(new Date());
Multipart mainParth = new MimeMultipart();
BodyPart html = new MimeBodyPart();
html.setContent(content, "text/html; charset=UTF-8");
mainParth.addBodyPart(html);
MimeBodyPart bodyPart = new MimeBodyPart();
if (fileSrc != null && fileSrc.length > 0) {
logger.info("附件数量:" + fileSrc.length);
URL url;
for (int i = 0; i < fileSrc.length; i++) {
String devAgreement =http;
if (fileSrc[i].startsWith(devAgreement)) {
logger.info("在线附件文件发送");
bodyPart = new MimeBodyPart();
url = new URL(fileSrc[i]);
DataSource dataSource = new URLDataSource(url);
DataHandler dataHandler = new DataHandler(dataSource);
bodyPart.setDataHandler(dataHandler);
mainParth.addBodyPart(bodyPart);
} else {
logger.info("附件文件发送含压缩文件");
bodyPart = new MimeBodyPart();
MimeBodyPart bodyPart2 = fileDecompression(bodyPart, fileSrc[i], fileName[i]);
mainParth.addBodyPart(bodyPart2);
logger.info("》》》退出");
}
}}logger.info("》》》内容进入");
mimeMessage.setContent(mainParth);
//mimeMessage.saveChanges();
logger.info("》》》发射");
Transport.send(mimeMessage);
logger.info("邮件发送结束");
}
/**
* @Description:解压服务器文件 不同服务器文件解压读取未解决
* @Title: fileDecompression
* @date 2019-11-01
* @param @param string 参数
* @return void 返回类型
* @throws @return void
* @param string
* @throws IOException
* @throws MessagingException
*/
private MimeBodyPart fileDecompression(MimeBodyPart bodyPart, String filePath, String fileName)
throws IOException, MessagingException {
logger.info("文件地址:" + filePath);
logger.info("文件名称:" + fileName);
File file = new File(filePath);
if (!file.exists()) {
fileError(file);
}boolean archiveFile = isArchiveFile(file);
if (archiveFile) {//zip压缩包
logger.info("压缩包邮件解析发送");
DataSource ds = new FileDataSource(file);
bodyPart.setDataHandler(new DataHandler(ds));
bodyPart.setFileName(MimeUtility.encodeWord(fileName, "UTF-8", "Q"));
logger.info("压缩包邮件解析结束");
return bodyPart;
} else {// 文件
logger.info("文件发送");
DataSource ds = new FileDataSource(file);
bodyPart.setDataHandler(new DataHandler(ds));
bodyPart.setFileName(MimeUtility.encodeWord(fileName, "UTF-8", "Q"));
return bodyPart;
}}
/**
* @Description: 抛出异常
* @Title: fileError
* @date 2019-11-05 17:48
* @param @param file 参数
* @return void 返回类型
* @throws @return void
* @param file
*/
private void fileError(File file) {
throw new RuntimeException("文件路径不正确");
}
/**
* 判断文件是否为一个压缩文件
*
* @param file
* @return
*/
public static boolean isArchiveFile(File file) {

if (file == null) {
return false;
}
if (file.isDirectory()) {
return false;
}
boolean isArchive = false;
InputStream input = null;
try {
input = new FileInputStream(file);
byte[] buffer = new byte[4];
int length = input.read(buffer, 0, 4);
if (length == 4) {
isArchive = (Arrays.equals(ZIP_HEADER_1, buffer)) || (Arrays.equals(ZIP_HEADER_2, buffer));
}} catch (IOException e) {
e.printStackTrace();
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
}}}
return isArchive;
}
/**
*
* @param mailString 待判断的mail邮件地址
* @return boolean 是否匹配成功
*/
public static boolean isMailAddr(String mailString) {
String pattenString = "^\\w+((-\\w+)|(\\.\\w+))*\\@[A-Za-z0-9]+((\\.|-)[A-Za-z0-9]+)*\\.[A-Za-z0-9]+$";
Pattern pattern = Pattern.compile(pattenString);
Matcher matcher = pattern.matcher(mailString);
return matcher.matches();
}

知识拓展:

multipart/form-data:

1、既可以提交普通键值对,也可以提交(多个)文件键值对。

2、HTTP规范中的Content-Type不包含此类型,只能用在POST提交方式下,属于http客户端(浏览器、java httpclient)的扩展

3、通常在浏览器表单中,或者http客户端(java httpclient)中使用。

application/octet-stream:

1、只能提交二进制,而且只能提交一个二进制,如果提交文件的话,只能提交一个文件,后台接收参数只能有一个,而且只能是流(或者字节数组)

2、属于HTTP规范中Content-Type的一种

3、很少使用

application/x-www-form-urlencoded

1、不属于http content-type规范,通常用于浏览器表单提交,数据组织格式:name1=value1&name2=value2,post时会放入http body,get时,显示在在地址栏。

2、所有键与值,都会被urlencoded,请查看urlencoder

解压压缩文件转换成字节流数组导入email容器中*

/**
* 根据文件路径获取ZIP字节流。
* @param zipFilePath
* @return
* @throws IOException
*/
public static byte[] getBytesByZip(String zipFilePath) throws IOException{
InputStream inputStream;
byte[] fileByte = null;
ZipFile zipFile = null;
try{
zipFile = new ZipFile(zipFilePath);
Enumeration<?> entries = zipFile.getEntries();
while (entries.hasMoreElements()){
ZipEntry entry = (ZipEntry)entries.nextElement();
inputStream = zipFile.getInputStream(entry);
fileByte = inputStreamToByte(inputStream);
inputStream.close();
}
} finally {
if (zipFile != null) {
zipFile.close();
}
}
return fileByte;
}

/**
* InputStream文件流转换成字节数组。
* @param in	文件流
* @return
* @throws IOException
*/
public static byte[] inputStreamToByte(InputStream in)
throws IOException{
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
byte[] data = new byte[1024];
int count = -1;
while((count = in.read(data, 0, 1024)) != -1) {
outStream.write(data, 0, count);
}outStream.close();
data = null;
return outStream.toByteArray();
}

发送附件的不同方式:

/**
* 发送邮件以及通过byte[]流或base64编码字符串发送邮件附件
* @param Notice
* @return void
*/
public void sendEmailByFlow(Notice notice) throws Exception {
boolean sessionDebug = false;
InternetAddress[] address = null;
SimpleDateFormat sdf = new SimpleDateFormat(“yyyy-MM-dd hh:mm:ss”);
try {

		SiteConfig  config = new SiteConfig();                    	//配置信息
String mailServer = config.getSendEmailSmtp();              //服务器地址
String mailAuth = config.getMailSmtpAuth();                 //验证
String mailAddress = config.getSendEmailAddress();          //邮箱
String mailUser = config.getSendEmailAddress();             //用户名
String mailPassword = config.getSendEmailPassword();        //密码
String mailSmtpPort = config.getMailSmtpPort();             //端口

Properties props = System.getProperties();
props.put("mail.smtp.host", mailServer);
props.put("mail.smtp.auth", mailAuth);

Session mailSession = Session.getDefaultInstance(props, null);
mailSession.setDebug(sessionDebug);

Message msg = new MimeMessage(mailSession);
msg.setFrom(new InternetAddress(mailAddress));
if (notice.getToAddress() != null && !"".equals(notice.getToAddress())) {
address = InternetAddress.parse(notice.getToAddress(), false);
for (InternetAddress addr:address) {
if (this.isEmail(addr.getAddress()) == false) {
log.info(sdf.format(new Date() + notice.getScene() + addr.getAddress() + "地址格式不正确。"));
}}msg.setRecipients(Message.RecipientType.TO, address);
}if (notice.getCcAddress() != null && !"".equals(notice.getCcAddress())) {
address = InternetAddress.parse(notice.getCcAddress(), false);
for (InternetAddress addr:address) {
if (this.isEmail(addr.getAddress()) == false) {
log.info(sdf.format(new Date() + notice.getScene() + addr.getAddress() + "地址格式不正确。"));
}}msg.setRecipients(Message.RecipientType.CC, address);
}if (notice.getBccAddress() != null && !"".equals(notice.getBccAddress())) {
address = InternetAddress.parse(notice.getBccAddress(), false);
for (InternetAddress addr:address) {
if (this.isEmail(addr.getAddress()) == false) {
log.info(sdf.format(new Date() + notice.getScene() + addr.getAddress() + "地址格式不正确。"));
}}msg.setRecipients(Message.RecipientType.BCC, address);
}
String message = notice.getContent();
msg.setSubject(notice.getTitle());
msg.setSentDate(new Date());

msg.setText(message);
Multipart mm = new MimeMultipart();
BodyPart mdp = new MimeBodyPart();                 //新建一个存放信件内容的BodyPart对象
mdp.setContent(message, "text/html;charset=UTF-8");
mm.addBodyPart(mdp);                               //将含有信件内容的BodyPart加入到MimeMultipart对象中

String[] fname = notice.getAttachFileName();
byte[] data = null;
String[] file64Str = notice.getFile64Str();
if (file64Str != null && file64Str.length > 0) {
BASE64Decoder base = new BASE64Decoder();
for (int i=0; i<fname.length; i++) {
data = base.decodeBuffer(file64Str[i]);
mdp = new MimeBodyPart();
DataSource obj = new ByteArrayDataSource(data, "application/octet-stream");
DataHandler dh = new DataHandler(obj);
mdp.setDataHandler(dh);
mdp.setFileName(MimeUtility.encodeWord(fname[i],"UTF-8","Q"));
mdp.setHeader("content-id", fname[i]);
mm.addBodyPart(mdp);
}} else {
data = notice.getFileFlow();
mdp = new MimeBodyPart();
DataSource obj = new ByteArrayDataSource(data, "application/octet-stream");
DataHandler dh = new DataHandler(obj);
mdp.setDataHandler(dh);
mdp.setFileName(MimeUtility.encodeWord(fname[0],"UTF-8","Q"));
mdp.setHeader("content-id", fname[0]);
mm.addBodyPart(mdp);
}
msg.setContent(mm);
msg.saveChanges();

Transport transport = mailSession.getTransport("smtp");
transport.connect(mailServer, Integer.parseInt(mailSmtpPort), mailUser, mailPassword);
transport.sendMessage(msg, msg.getAllRecipients());
transport.close();

} catch (MessagingException e) {
e.printStackTrace();
log.error(sdf.format(new Date() + notice.getScene() + "异常错误,邮件发送失败。"));
throw e;
}}
private boolean isEmail(String str) {
String regex = "^([\\w-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([\\w-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?)$";
return match(regex, str);
}
private boolean match(String regex, String str) {
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(str);
return matcher.matches();
}
/**
*  根据byte数组,生成文件。
* @param filePath	目标文件路径
* @return
* @throws IOException
*/
public static void toRealFile(byte[] bfile, String filePath)
throws IOException {
BufferedOutputStream bos = null;
FileOutputStream fos = null;
File file = null;
try {
file = new File(filePath);
fos = new FileOutputStream(file);
bos = new BufferedOutputStream(fos);
bos.write(bfile);
} finally {
if (bos != null) {
bos.close();
}if (fos != null) {
fos.close();
}}}
  • 点赞
  • 收藏
  • 分享
  • 文章举报
YHM_MM 发布了45 篇原创文章 · 获赞 2 · 访问量 3184 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: