使用者註冊 → 系統產生啟動碼 → 發送 HTML 郵件含啟動連結 → 使用者點擊連結 → 驗證碼比對 → 啟用帳號。
package cn.itcast.shop.utils;
import javax.mail.*;
import javax.mail.internet.*;
import java.util.Properties;
public class MailUtils {
public static void sendMail(String to, String code) {
// 1. Session 設定
Properties props = new Properties();
props.setProperty("mail.host", "localhost"); // 易郵郵件伺服器
props.setProperty("mail.smtp.auth", "true");
Session session = Session.getDefaultInstance(props, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("service@azz.com", "111");
}
});
// 2. 建立 MimeMessage
MimeMessage message = new MimeMessage(session);
try {
// 寄件者
message.setFrom(new InternetAddress("service@azz.com"));
// 收件者
message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
// 主旨
message.setSubject("來自周洲商城的官方啟動郵件");
// HTML 內容
String url = "https://192.168.21.114:8080/shop/user_active.action?code=" + code;
String content = "<h1>AZZ商城官方啟動郵件!點下方連結完成啟動操作!</h1>" +
"<h3><a href='" + url + "'>" + url + "</a></h3>";
message.setContent(content, "text/html;charset=UTF-8");
// 3. 發送
Transport.send(message);
} catch (MessagingException e) {
e.printStackTrace();
}
}
}
@Service
@Transactional
public class UserService {
@Autowired
private UserDao userDao;
public void register(User user) {
// 1. 狀態 0 = 未啟用
user.setState(0);
// 2. 產生唯一啟動碼
String code = UUIDUtils.getUUID() + UUIDUtils.getUUID();
user.setCode(code);
// 3. 存入資料庫
userDao.save(user);
// 4. 非同步發送郵件(建議用 @Async 或 MQ)
MailUtils.sendMail(user.getEmail(), code);
}
public User findByCode(String code) {
return userDao.findByCode(code);
}
public void activate(User user) {
user.setState(1); // 已啟用
userDao.update(user);
}
}
@Controller
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/user_active.action")
public String active(@RequestParam String code) {
User user = userService.findByCode(code);
if (user != null) {
userService.activate(user);
return "activeSuccess"; // 跳轉成功頁
}
return "activeFail"; // 失敗頁
}
}
| 環節 | 關鍵點 |
|---|---|
| 啟動碼生成 | UUID 雙重拼接,極低碰撞機率;或用 JWT 簽名 Token |
| 郵件內容 | HTML 格式 + 絕對路徑連結,避免相對路徑在郵件客戶端失效 |
| SMTP 設定 | 本地易郵伺服器需啟用 SMTP、設定帳號密碼、開放連接埠 |
| 非同步發送 | 註冊主流程不阻塞,使用 @Async、CompletableFuture 或訊息佇列 |
| 防重複發送 | 資料庫唯一索引 (email) + 狀態機制,避免重複註冊發信 |
| 安全性 | 啟動碼一次性、時效性(如 24 小時過期)、HTTPS 連結 |
JavaMailSender 簡化配置JavaMail 配合 Spring 實現註冊啟動信是經典入門案例。掌握 MimeMessage HTML 內容建構、SMTP 認證設定、非同步發送與啟動碼安全設計,即可構建可靠的用戶驗證通道。實務中務必重視「非同步解耦」與「模板化維護」,為後續擴充奠基。