1 import java.io.FileOutputStream; 2 import java.io.IOException; 3 import java.io.OutputStream; 4 import java.io.UnsupportedEncodingException; 5 import java.util.Calendar; 6 import java.util.Date; 7 import java.util.HashSet; 8 import java.util.Properties; 9 import java.util.Set; 10 import java.util.regex.Matcher; 11 import java.util.regex.Pattern; 12 import javax.mail.MessagingException; 13 import javax.mail.Session; 14 import javax.mail.Transport; 15 import javax.mail.internet.InternetAddress; 16 import javax.mail.internet.MimeMessage; 17 18 import com.yanfuchang.work.utils.fileIo.FileUtils; 19 20 public class MailSendUtil { 21 /** 22 * 验证邮箱 23 */ 24 public static boolean checkEmail(String email) { 25 boolean flag = false; 26 try { 27 String check = "^([a-z0-9A-Z]+[-|_|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$"; 28 Pattern regex = Pattern.compile(check); 29 Matcher matcher = regex.matcher(email); 30 flag = matcher.matches(); 31 } catch (Exception e) { 32 flag = false; 33 } 34 return flag; 35 } 36 37 /** 38 * 验证手机号码,11位数字,1开通,第二位数必须是3456789这些数字之一 * 39 */ 40 public static boolean checkMobileNumber(String mobileNumber) { 41 boolean flag = false; 42 try { 43 Pattern regex = Pattern.compile("^1[345789]\\d{9}$"); 44 Matcher matcher = regex.matcher(mobileNumber); 45 flag = matcher.matches(); 46 } catch (Exception e) { 47 e.printStackTrace(); 48 flag = false; 49 } 50 return flag; 51 } 52 53 private String fromAddr; // 发件人邮箱 54 private String password; // 发件人密码 55 private String smtpHost; // smtp 主机地址 56 private boolean bAuthorOpen = true; // 是否授权验证 57 private boolean bSSLOpen = false; // 是否开启SSL 58 private String smtpPort = "25"; // smtp端口 默认 25 SSL 465或587 59 private Set<String> recToList = null; // 收件人列表 60 private Set<String> recCCList = null; // 抄送人列表 61 private Set<String> recBCCList = null; // 密送人列表 62 private String subjectText = "test"; // 邮件主题 63 private String context = "test"; // 发送内容 64 private boolean bSaveEml = false; // 是否保存邮件.eml 65 private String charset = "UTF-8"; // 发送字符编码 UTF-8 GB2312 66 67 private String timeOut = "250000"; 68 private String savePath = "c:\\email\\"; 69 70 public MailSendUtil() { 71 } 72 73 public String getCharset() { 74 return charset; 75 } 76 77 public String getContext() { 78 return context; 79 } 80 81 public String getFromAddr() { 82 return fromAddr; 83 } 84 85 public String getPassword() { 86 return password; 87 } 88 89 public Set<String> getRecBCCList() { 90 return recBCCList; 91 } 92 93 public Set<String> getRecCCList() { 94 return recCCList; 95 } 96 97 public Set<String> getRecToList() { 98 return recToList; 99 } 100 101 public String getSavePath() { 102 return savePath; 103 } 104 105 public String getSmtpHost() { 106 return smtpHost; 107 } 108 109 public String getSmtpPort() { 110 return smtpPort; 111 } 112 113 public String getSubjectText() { 114 return subjectText; 115 } 116 117 public String getTimeOut() { 118 return timeOut; 119 } 120 121 public boolean isbAuthorOpen() { 122 return bAuthorOpen; 123 } 124 125 public boolean isbSaveEml() { 126 return bSaveEml; 127 } 128 129 public boolean isbSSLOpen() { 130 return bSSLOpen; 131 } 132 133 public boolean SendEmail() { 134 if (fromAddr == null || password == null || subjectText == null || context == null) { 135 return false; 136 } 137 boolean validEmail = checkEmail(fromAddr); 138 if (!validEmail) { 139 return false; 140 } 141 int nSize = 0; 142 for (String string : recToList) { 143 boolean checkEmail1 = checkEmail(string); 144 if (checkEmail1) { 145 nSize++; 146 } 147 } 148 if (nSize == 0) { 149 return false; 150 } 151 Properties props = new Properties(); // 参数配置 152 props.setProperty("mail.transport.protocol", "smtp"); // 使用的协议(JavaMail规范要求) 153 props.setProperty("mail.smtp.host", smtpHost); // 发件人的邮箱的 SMTP 服务器地址 154 props.setProperty("mail.smtp.port", smtpPort); 155 props.setProperty("mail.smtp.timeout", timeOut); 156 if (bAuthorOpen) { 157 props.setProperty("mail.smtp.auth", "true"); // 需要请求认证 158 } else { 159 props.setProperty("mail.smtp.auth", "false"); // 需要请求认证 160 } 161 if (bSSLOpen) { 162 /* 163 * PS: 某些邮箱服务器要求 SMTP 连接需要使用 SSL 安全认证 (为了提高安全性, 邮箱支持SSL连接, 也可以自己开启), 164 * 如果无法连接邮件服务器, 仔细查看控制台打印的 log, 如果有有类似 “连接失败, 要求 SSL 安全连接” 等错误, 开启 SSL 安全连接。 165 * SMTP 服务器的端口 (非 SSL 连接的端口一般默认为 25, 可以不添加, 如果开启了 SSL 连接, 需要改为对应邮箱的 SMTP 服务器的端口, 166 * 具体可查看对应邮箱服务的帮助, QQ邮箱的SMTP(SLL)端口为465或587, 其他邮箱自行去查看 167 */ 168 props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); 169 props.setProperty("mail.smtp.socketFactory.fallback", "false"); 170 props.setProperty("mail.smtp.socketFactory.port", smtpPort); 171 } 172 173 // 2. 根据配置创建会话对象, 用于和邮件服务器交互 174 Session session = Session.getInstance(props); 175 session.setDebug(true); // 设置为debug模式, 可以查看详细的发送 log 176 177 // 3. 创建一封邮件 178 MimeMessage message = new MimeMessage(session); // 创建邮件对象 179 // 3.1. From: 发件人 180 // 其中 InternetAddress 的三个参数分别为: 邮箱, 显示的昵称(只用于显示, 没有特别的要求), 昵称的字符集编码 181 // 真正要发送时, 邮箱必须是真实有效的邮箱。 182 boolean checkEmail = checkEmail(fromAddr); 183 if (checkEmail) { 184 String showName = StringUtils.substringBefore(fromAddr, "@"); 185 try { 186 message.setFrom(new InternetAddress(fromAddr, showName, charset)); 187 } catch (UnsupportedEncodingException | MessagingException e) { 188 e.printStackTrace(); 189 } 190 } else { 191 return false; 192 } 193 // 3.2. To: 收件人 194 int nRecTo = 0; 195 for (String recTo : recToList) { 196 boolean checkEmail1 = checkEmail(recTo); 197 if (checkEmail1) { 198 String showName = StringUtils.substringBefore(recTo, "@"); 199 try { 200 if (nRecTo == 0) { 201 nRecTo++; 202 message.setRecipient(MimeMessage.RecipientType.TO, 203 new InternetAddress(recTo, showName, charset)); 204 } else { 205 message.addRecipient(MimeMessage.RecipientType.TO, 206 new InternetAddress(recTo, showName, charset)); 207 } 208 209 } catch (UnsupportedEncodingException | MessagingException e) { 210 e.printStackTrace(); 211 } 212 } 213 } 214 // 3.3 Cc: 抄送(可选) 215 int nRecCC = 0; 216 for (String recCC : recCCList) { 217 boolean checkEmail1 = checkEmail(recCC); 218 if (checkEmail1) { 219 String showName = StringUtils.substringBefore(recCC, "@"); 220 try { 221 if (nRecCC == 0) { 222 message.setRecipient(MimeMessage.RecipientType.CC, 223 new InternetAddress(recCC, showName, charset)); 224 } else { 225 message.addRecipient(MimeMessage.RecipientType.CC, 226 new InternetAddress(recCC, showName, charset)); 227 } 228 229 } catch (UnsupportedEncodingException | MessagingException e) { 230 e.printStackTrace(); 231 } 232 } 233 } 234 // 3.5 Bcc: 密送(可选) 235 int nRecBcc = 0; 236 for (String recBCC : recBCCList) { 237 boolean checkEmail1 = checkEmail(recBCC); 238 if (checkEmail1) { 239 String showName = StringUtils.substringBefore(recBCC, "@"); 240 try { 241 if (nRecBcc == 0) { 242 message.setRecipient(MimeMessage.RecipientType.BCC, 243 new InternetAddress(recBCC, showName, charset)); 244 } else { 245 message.addRecipient(MimeMessage.RecipientType.BCC, 246 new InternetAddress(recBCC, showName, charset)); 247 } 248 } catch (UnsupportedEncodingException | MessagingException e) { 249 e.printStackTrace(); 250 } 251 } 252 } 253 254 try { 255 // 3.6. Subject: 邮件主题 256 message.setSubject(subjectText, charset); 257 // 3.7. Content: 邮件正文(可以使用html标签) 258 message.setContent(context, "text/html;charset=" + charset); 259 // 3.8. 设置显示的发件时间 260 message.setSentDate(new Date()); 261 // 3.9. 保存前面的设置 262 message.saveChanges(); 263 } catch (MessagingException e) { 264 e.printStackTrace(); 265 return false; 266 } 267 268 // 3.10. 将该邮件保存到本地 269 if (bSaveEml) { 270 try { 271 if (savePath == null) { 272 savePath = "c:\\smartEmail\\"; 273 } 274 Calendar calendar = Calendar.getInstance(); 275 long timeInMillis = calendar.getTimeInMillis(); 276 FileUtils.createDirectory(savePath); 277 OutputStream out = new FileOutputStream(savePath + timeInMillis + ".eml"); 278 message.writeTo(out); 279 out.flush(); 280 out.close(); 281 } catch (IOException | MessagingException e) { 282 e.printStackTrace(); 283 } 284 } 285 try { 286 // 4. 根据 Session 获取邮件传输对象 287 Transport transport = session.getTransport(); 288 // 5. 使用 邮箱账号 和 密码 连接邮件服务器, 这里认证的邮箱必须与 message 中的发件人邮箱一致, 否则报错 289 // PS_01: 成败的判断关键在此一句, 如果连接服务器失败, 都会在控制台输出相应失败原因的 log, 290 // 仔细查看失败原因, 有些邮箱服务器会返回错误码或查看错误类型的链接, 根据给出的错误 291 // 类型到对应邮件服务器的帮助网站上查看具体失败原因。 292 // PS_02: 连接失败的原因通常为以下几点, 仔细检查代码: 293 // (1) 邮箱没有开启 SMTP 服务; 294 // (2) 邮箱密码错误, 例如某些邮箱开启了独立密码; 295 // (3) 邮箱服务器要求必须要使用 SSL 安全连接; 296 // (4) 请求过于频繁或其他原因, 被邮件服务器拒绝服务; 297 // (5) 如果以上几点都确定无误, 到邮件服务器网站查找帮助。 298 transport.connect(fromAddr, password); 299 // (6). 发送邮件, 发到所有的收件地址, message.getAllRecipients() 获取到的是在创建邮件对象时添加的所有收件人, 抄送人, 300 transport.sendMessage(message, message.getAllRecipients()); 301 // (7). 关闭连接 302 transport.close(); 303 return true; 304 } catch (MessagingException e) { 305 e.printStackTrace(); 306 return false; 307 } 308 } 309 310 public void setbAuthorOpen(boolean bAuthorOpen) { 311 this.bAuthorOpen = bAuthorOpen; 312 } 313 314 public void setbSaveEml(boolean bSaveEml) { 315 this.bSaveEml = bSaveEml; 316 } 317 318 public void setbSSLOpen(boolean bSSLOpen) { 319 this.bSSLOpen = bSSLOpen; 320 } 321 322 public void setCharset(String charset) { 323 this.charset = charset; 324 } 325 326 public void setContext(String context) { 327 this.context = context; 328 } 329 330 public void setFromAddr(String fromAddr) { 331 this.fromAddr = fromAddr; 332 } 333 334 public void setPassword(String password) { 335 this.password = password; 336 } 337 338 public void setRecBCCList(Set<String> recBCCList) { 339 this.recBCCList = recBCCList; 340 } 341 342 public void setRecCCList(Set<String> recCCList) { 343 this.recCCList = recCCList; 344 } 345 346 public void setRecToList(Set<String> recToList) { 347 this.recToList = recToList; 348 } 349 350 public void setSavePath(String savePath) { 351 this.savePath = savePath; 352 } 353 354 public void setSmtpHost(String smtpHost) { 355 this.smtpHost = smtpHost; 356 } 357 358 public void setSmtpPort(String smtpPort) { 359 this.smtpPort = smtpPort; 360 } 361 362 public void setSubjectText(String subjectText) { 363 this.subjectText = subjectText; 364 } 365 366 public void setTimeOut(String timeOut) { 367 this.timeOut = timeOut; 368 } 369 370 public static void main(String[] args) { 371 MailSendUtil emailUtil = new MailSendUtil(); 372 emailUtil.setFromAddr(""); 373 emailUtil.setPassword(""); 374 emailUtil.setbAuthorOpen(true); 375 emailUtil.setbSaveEml(true); 376 emailUtil.setbSSLOpen(true); 377 emailUtil.setCharset("UTF-8"); 378 emailUtil.setContext("this is a test!"); 379 emailUtil.setSmtpHost("smtp.ym.163.com"); 380 emailUtil.setSmtpPort("465"); 381 emailUtil.setSubjectText("test"); 382 Set<String> recToList = new HashSet<String>(); 383 recToList.add("[email protected]"); 384 emailUtil.setRecToList(recToList); 385 Set<String> recCCList = new HashSet<String>(); 386 recCCList.add("[email protected]"); 387 emailUtil.setRecCCList(recCCList); 388 Set<String> recBCCList = new HashSet<String>(); 389 recBCCList.add("[email protected]"); 390 emailUtil.setRecBCCList(recBCCList); 391 boolean sendEmail = emailUtil.SendEmail(); 392 System.out.println(sendEmail); 393 } 394 }
依赖:
1 <!-- mail --> 2 <dependency> 3 <groupId>javax.mail</groupId> 4 <artifactId>mail</artifactId> 5 <version>1.4</version> 6 </dependency>