package com.walker.push.mail; import com.walker.infrastructure.utils.StringUtils; import com.walker.push.AbstractPushObject; import com.walker.push.Notification; import com.walker.push.NotificationChannel; import com.walker.push.PushException; import com.walker.push.PushResult; import com.walker.push.util.PushUtils; import javax.mail.Address; import javax.mail.Message; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Properties; /** * 标准的邮件推送实现。同步调用 * @author 时克英 * @date 2023-04-22 */ public abstract class MailPush extends AbstractPushObject { private MyAuthenticator authenticator = null; public MailPush(){ this.setId(NotificationChannel.INDEX_MAIL); this.setName(NotificationChannel.NAME_MAIL); } @Override protected PushResult doPushContent(Notification notification, List data) throws PushException { PushResult pushResult = PushUtils.acquireSuccessPushResult(); for(MailSenderInfo mailInfo : data){ Properties pro = mailInfo.getProperties(); // 根据邮件会话属性和密码验证器构造一个发送邮件的session Session sendMailSession = Session.getDefaultInstance(pro, this.authenticator); try { // 根据session创建一个邮件消息 Message mailMessage = new MimeMessage(sendMailSession); // 创建邮件发送者地址 Address from = new InternetAddress(mailInfo.getFromAddress()); // 设置邮件消息的发送者 mailMessage.setFrom(from); // 创建邮件的接收者地址,并设置到邮件消息中 Address to = new InternetAddress(mailInfo.getToAddress()); mailMessage.setRecipient(Message.RecipientType.TO,to); // 设置邮件消息的主题 mailMessage.setSubject(mailInfo.getSubject()); // 设置邮件消息发送的时间 mailMessage.setSentDate(new Date()); // 是否是html格式,暂时只有纯文本 // 设置邮件消息的主要内容 String mailContent = mailInfo.getContent(); mailMessage.setText(mailContent); // 发送邮件 Transport.send(mailMessage); logger.debug("成功发送'通知邮件': {}", mailContent); } catch (Exception ex){ logger.error("发送'通知邮件'失败: " + mailInfo.getContent(), ex); pushResult.setCode(99); pushResult.setText(ex.getMessage()); // pushResult.addOneFailed(mailInfo.getToAddress()); pushResult.addOneFailed(mailInfo.getUser()); } } return pushResult; } @Override public NotificationChannel getNotificationChannel() { return NotificationChannel.Mail; } @Override public List translateToTarget(Notification notification) { List data = new ArrayList<>(2); MailSenderInfo mailSenderInfo = null; String toAddress = null; for(String user: notification.getReceiverList()){ mailSenderInfo = new MailSenderInfo(); mailSenderInfo.setMailServerHost(this.mailServerHost); mailSenderInfo.setMailServerPort(this.mailServerPort); mailSenderInfo.setValidate(true); mailSenderInfo.setUserName(this.fromAddress); mailSenderInfo.setPassword(this.fromPassword); mailSenderInfo.setFromAddress(this.fromAddress); // 转换前,要记录原始发送用户id mailSenderInfo.setUser(user); if(user.indexOf(StringUtils.STRING_AT) > 0){ // 说明直接是邮箱地址 toAddress = user; } else { // 让业务转换为邮箱 toAddress = this.getUserMail(user); } if(StringUtils.isEmpty(toAddress)){ logger.error("根据用户id未找到'email'地址,该推送消息忽略。user={}", user); continue; } mailSenderInfo.setToAddress(toAddress); mailSenderInfo.setSubject(notification.getTitle()); mailSenderInfo.setContent(notification.getContent()); data.add(mailSenderInfo); } return data; } @Override public void startup(){ if(StringUtils.isEmpty(this.fromAddress) || StringUtils.isEmpty(this.fromPassword)){ throw new IllegalArgumentException("需要先设置邮件发送者信息: fromAddress, fromPassword!"); } if(authenticator == null){ authenticator = new MyAuthenticator(this.fromAddress, this.fromPassword); } } /** * 根据用户id,获取email地址 * @param userId * @return */ protected abstract String getUserMail(String userId); /** * 设置邮件服务地址 * @param mailServerHost */ public void setMailServerHost(String mailServerHost) { this.mailServerHost = mailServerHost; } /** * 设置邮件服务端口,默认:25 * @param mailServerPort */ public void setMailServerPort(String mailServerPort) { this.mailServerPort = mailServerPort; } /** * 设置发送邮件地址 * @param fromAddress */ public void setFromAddress(String fromAddress) { this.fromAddress = fromAddress; } /** * 设置发送邮件密码(现在是密钥,不是登录邮箱密码) * @param fromPassword */ public void setFromPassword(String fromPassword) { this.fromPassword = fromPassword; } private String mailServerHost; private String mailServerPort; private String fromAddress; private String fromPassword; }