总结日志
- 用Spring java发邮件给指定的客户
- 设置注册、激活流程和页面
目录 总结日志Java 发邮件注册功能
Java 发邮件
首先需要将将发信箱设置成支持第三方 POP3和SMTP服务开启状态
在application中进行相关配置
# MailProperties
spring.mail.host = smtp.163.com // 发送邮件的发送方
spring.mail.port=465 // 邮件默认端口号一般都是465
spring.mail.username=@163.com // 发送的地址
spring.mail.password= // 第三方密码
spring.mail.protocol=smtps // protocol服务
spring.mail.peoperties.mail.smtp.ssl.enalbe=true // 启用ssl服务
在util下新建一个邮箱发送类
@Component // 要可以被扫描到
public class MailClient {
private static final Logger logger = LoggerFactory.getLogger(MailClient.class);
@Autowired
private JavaMailSender mailSender;// 注入自带的邮箱发送依赖
@Value("${spring.mail.username}")
private String from;// 从配置文件获得发送的地址
public void sendMail(String to, String subject, String content){
try {
// 邮件信息封装类
MimeMessage message = mailSender.createMimeMessage();
// 一个邮件信息的封装类,帮助我们构造邮件内的信息
MimeMessageHelper helper = new MimeMessageHelper(message);
helper.setFrom(from);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(content, true); // 是否可以返回html的解析文件
mailSender.send(helper.getMimeMessage()); // 发送
} catch (MessagingException e) {
logger.error("发送邮件失败"+e.getMessage());
}
}
测试发送一个文本给对应的邮箱
@Test
public void testTextMail(){
mailClient.sendMail("735110067@qq.com", "Test", "发送成功");
}
测试发送一个html给邮箱,html对应的模板在mail.demo.html。这里使用了一个模板引擎TemplateEngine
@Test
public void testHtmlMail(){
Context context = new Context();
context.setVariable("username", "sunday");
String content = templateEngine.process("/mail/demo", context);
System.out.println(content);
mailClient.sendMail("735110067@qq.com", "HTML", content);
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>邮件示例</title>
</head>
<body>
<p>欢迎 <span style="color:red" th:text="${username}"></span></p>
</body>
</html>
上面的conrtext是一个文件内容,设置了一个发送的内容,并设置了k-v关键词username为sunday.则就会在下面的html的th动态模板中填充。这个示例发送了一个html的主题为HTML的邮件内容为sunday变红的邮件。
https://zhuanlan.zhihu.com/p/370443415 JavaMail发送邮件时,可使用模板引擎TemplateEngine,生成HTML内容
生成h5页面可用于发送邮件模板,可避免
- 用Java代码创建基于HTML的电子邮件内容很繁琐且容易出错。
- 显示逻辑和业务逻辑之间没有明确的区分。
- 更改电子邮件内容的显示结构需要编写Java代码,重新编译,重新部署等
注册功能
注册页面如图所示,流程可以概括为:
- 首先在页面上输出个人信息,然后页面返回一个user对象
- 控制端将html返回的对象送到服务端,服务端根据该用户的账号及邮箱去数据端搜素,看有没有重复的用户
- 如果数据端有重复的用户,则返回错误信息列表,否则向sql中插入用户,并返回空信息列表
- 控制端得到返回的信息,如果有错误信息,则在html页面上显示错误,否则注册成功发送邮件
- 点激活邮件,判断激活是否正确,正确的话将user的status设置为1,激活态,并返回登录界面,准备登录
- 打开注册页面
-
@RequestMapping(path="/register", method= RequestMethod.GET) public String getRegisterPage(){ return "/site/register"; } // "/site/register/html"
- 先写一个用户出否存在的服务端对象
-
public Map<String, Object> register(User user){// user是从html获得的用户对象 Map<String, Object> map = new HashMap<>();// 返回的错误信息列表 // 对空值进行判断处理 if(user==null){ throw new IllegalArgumentException("参数不能为空"); } if(StringUtils.isBlank(user.getPassword())){ map.put("usernameMsg","密码不能为空"); return map; } if(StringUtils.isBlank(user.getUsername())){ map.put("usernameMsg","账号不能为空"); return map; } if(StringUtils.isBlank(user.getEmail())){ map.put("usernameMsg","邮箱不能为空"); return map; } //验证账号是否已经存在 User u = userMapper.selectByName(user.getUsername()); if(u!=null){ map.put("usernameMsg", "该账号已存在"); return map; } //验证邮箱 u = userMapper.selectByEmail(user.getEmail()); if(u!=null){ map.put("emailMsg", "邮箱已经被注册"); return map; } // 注册用户 user.setSalt(CommunityUtil.generateUUID().substring(0, 5)); user.setPassword(CommunityUtil.md5(user.getPassword()+user.getSalt())); user.setType(0); user.setStatus(0); user.setActivationCode(CommunityUtil.generateUUID()); user.setHeaderUrl(String.format("http://images.nowcoder.com/head/%dt.png", new Random().nextInt(1000)));// 随机生成头像 user.setCreateTime(new Date()); // 创建时间 userMapper.insertUser(user); // 插入用户 //发送激活邮件 Context context = new Context(); context.setVariable("email", user.getEmail()); // 激活路径 // http://localhost:8080/community/activation/101/code String url = domain + contextPath + "/activation/" + user.getId() + "/"+user.getActivationCode(); // contextPath 是community,字符串拼接 context.setVariable("url",url); String content = templateEngine.process("/mail/activation", context); mailClient.sendMail(user.getEmail(), "激活账号", content); return map; } 下面这个对象用来生成随机字符串作为salt加入密码中,将salt和用户密码使用md5加密 public class CommunityUtil { // 随机字符串 激活码 public static String generateUUID(){ return UUID.randomUUID().toString().replaceAll("_", " "); } // MD5 加密 public static String md5(String key){ if(StringUtils.isBlank(key)){ return null; } return DigestUtils.md5DigestAsHex(key.getBytes());// 按字节加密 } } 这是activation.html <!doctype html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="utf-8"> <link rel="icon" href="https://static.nowcoder.com/images/logo_87_87.png"/> <title>牛客网-激活账号</title> </head> <body> <div> <p> <b th:text="${email}">xxx@xxx.com</b>, 您好! </p> <p> 您正在注册牛客网, 这是一封激活邮件, 请点击 <a th:href="${url}">此链接</a>, 激活您的牛客账号! </p> </div> </body> </html> register.html的内容部分 <!-- 内容 --> <div class="main"> <div class="container pl-5 pr-5 pt-3 pb-3 mt-3 mb-3"> <h3 class="text-center text-info border-bottom pb-3">注 册</h3> <form class="mt-5" method="post" th:action="@{/register}"> <div class="form-group row"> <label for="username" class="col-sm-2 col-form-label text-right">账号:</label> <div class="col-sm-10"> <input type="text" th:class="|form-control ${usernameMsg!=null?'is-invalid':''}|" th:value = "${user!=null?user.username:''}" id="username" name="username" placeholder="请输入您的账号!" required> <div class="invalid-feedback" th:text="${usernameMsg}"> 该账号已存在! </div> </div> </div> <div class="form-group row mt-4"> <label for="password" class="col-sm-2 col-form-label text-right">密码:</label> <div class="col-sm-10"> <input type="password" th:class="|form-control ${passwordMsg!=null? 'is-invalid':''}|" th:value = "${user!=null?user.password:''}" id="password" name="password" placeholder="请输入您的密码!" required> <div class="invalid-feedback" th:text="${passwordMsg}"> 密码长度不能小于8位! </div> </div> </div> <div class="form-group row mt-4"> <label for="confirm-password" class="col-sm-2 col-form-label text-right">确认密码:</label> <div class="col-sm-10"> <input type="password" class="form-control" th:value = "${user!=null?user.password:''}" id="confirm-password" placeholder="请再次输入密码!" required> <div class="invalid-feedback"> 两次输入的密码不一致! </div> </div> </div> <div class="form-group row"> <label for="email" class="col-sm-2 col-form-label text-right">邮箱:</label> <div class="col-sm-10"> <input type="email" th:class="|form-control ${emailMsg!=null? 'is-invalid':''}|" th:value = "${user!=null?user.email:''}" id="email" name="email" placeholder="请输入您的邮箱!" required> <div class="invalid-feedback" th:text="${emailMsg}"> 该邮箱已注册! </div> </div> </div> <div class="form-group row mt-4"> <div class="col-sm-2"></div> <div class="col-sm-10 text-center"> <button type="submit" class="btn btn-info text-white form-control">立即注册</button> </div> </div> </form> </div> </div> ``` 定义一个接口,用于返回状态
激活函数public interface CommunityConstant { // 成功 int ACTIVATION_SUCCESS = 0; // 重复激活 int ACTIVATION_REPEAT = 1; // 激活失败 int ACTIVATION_FAILURE=2; }```
@RequestMapping(path="/activation/{userId}/{code}", method = RequestMethod.GET) public String activation(Model model, @PathVariable("userId") int userId, @PathVariable("code") String code){ int result = userService.activation(userId, code); if(result==ACTIVATION_SUCCESS){ model.addAttribute("msg", "激活成功,账号可以使用了"); model.addAttribute("target", "/login"); }else if(result==ACTIVATION_REPEAT){ model.addAttribute("msg", "无效操作,重复激活"); model.addAttribute("target", "/index"); }else{ model.addAttribute("msg", "激活失败,不匹配激活码"); model.addAttribute("target", "/index"); } return "/site/operate-result"; }```` @PathVariable 映射 URL 绑定的占位符 - 带占位符的 URL 是 Spring3.0 新增的功能,该功能在SpringMVC 向 REST 目标挺进发展过程中具有里程碑的意义 - 通过 @PathVariable 可以将 URL 中占位符参数绑定到控制器处理方法的入参中:URL 中的 {xxx} 占位符可以通过@PathVariable(“xxx“) 绑定到操作方法的入参中。 operator-result.html <!-- 内容 --> <div class="main"> <div class="container mt-5"> <div class="jumbotron"> <p class="lead" th:text="${msg}">您的账号已经激活成功,可以正常使用了!</p> <hr class="my-4"> <p> 系统会在 <span id="seconds" class="text-danger">8</span> 秒后自动跳转, 您也可以点此 <a id="target" th:href="@{${target}}" class="text-primary">链接</a>, 手动跳转! </p> </div> </div> </div>