PageRenderTime 54ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/projects/mvnforum-1.2.2-ga/myvietnam/src/net/myvietnam/mvncore/util/MailUtil.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 580 lines | 402 code | 66 blank | 112 comment | 115 complexity | 4bc24003d4cedb7d915b8268eafae90b MD5 | raw file
  1. /*
  2. * $Header: /cvsroot/mvnforum/myvietnam/src/net/myvietnam/mvncore/util/MailUtil.java,v 1.65.2.1 2010/04/27 11:27:31 minhnn Exp $
  3. * $Author: minhnn $
  4. * $Revision: 1.65.2.1 $
  5. * $Date: 2010/04/27 11:27:31 $
  6. *
  7. * ====================================================================
  8. *
  9. * Copyright (C) 2002-2007 by MyVietnam.net
  10. *
  11. * All copyright notices regarding MyVietnam and MyVietnam CoreLib
  12. * MUST remain intact in the scripts and source code.
  13. *
  14. * This library is free software; you can redistribute it and/or
  15. * modify it under the terms of the GNU Lesser General Public
  16. * License as published by the Free Software Foundation; either
  17. * version 2.1 of the License, or (at your option) any later version.
  18. *
  19. * This library is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  22. * Lesser General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU Lesser General Public
  25. * License along with this library; if not, write to the Free Software
  26. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  27. *
  28. * Correspondence and Marketing Questions can be sent to:
  29. * info at MyVietnam net
  30. *
  31. * @author: Minh Nguyen
  32. * @author: Mai Nguyen
  33. */
  34. package net.myvietnam.mvncore.util;
  35. import java.io.IOException;
  36. import java.io.UnsupportedEncodingException;
  37. import java.net.InetAddress;
  38. import java.net.UnknownHostException;
  39. import java.util.*;
  40. import javax.mail.*;
  41. import javax.mail.Flags.Flag;
  42. import javax.mail.internet.*;
  43. import javax.naming.InitialContext;
  44. import javax.naming.NamingException;
  45. import net.myvietnam.mvncore.MVNCoreConfig;
  46. import net.myvietnam.mvncore.MVNCoreConfig.MailConfig;
  47. import net.myvietnam.mvncore.exception.BadInputException;
  48. import net.myvietnam.mvncore.filter.DisableHtmlTagFilter;
  49. import org.apache.commons.logging.Log;
  50. import org.apache.commons.logging.LogFactory;
  51. import org.masukomi.aspirin.core.MailQue;
  52. public final class MailUtil {
  53. public static final int MAX_MESSAGES_PER_TRANSPORT = 100;
  54. private static final Log log = LogFactory.getLog(MailUtil.class);
  55. private MailUtil() {// prevent instantiation
  56. }
  57. //private static MailOptions mailOption = new MailOptions();
  58. /**
  59. * Get the user name part of an email. Ex: input: test@yahoo.com => output: test
  60. * @param email String the email
  61. * @return String the user name part of an email
  62. */
  63. public static String getEmailUsername(String email) {
  64. if (email == null) return "";
  65. int atIndex = email.indexOf('@');
  66. if (atIndex == -1) {
  67. return "";
  68. }
  69. return email.substring(0, atIndex);
  70. }
  71. /**
  72. * Get the domain part of an email. Ex: input: test@yahoo.com => output: yahoo.com
  73. * @param email String the email
  74. * @return String the user name part of an email
  75. */
  76. public static String getEmailDomain(String email) {
  77. if (email == null) return "";
  78. int atIndex = email.indexOf('@');
  79. if (atIndex == -1) {
  80. return "";
  81. }
  82. return email.substring(atIndex + 1);
  83. }
  84. /**
  85. * Check if an email is good and safe or not.
  86. * This method should be use for all email input from user
  87. * @param input String
  88. * @throws BadInputException if email is not good
  89. */
  90. public static void checkGoodEmail(String input) throws BadInputException {
  91. if (input == null) throw new BadInputException("Sorry, null string is not a good email.");//@todo : localize me
  92. int atIndex = input.indexOf('@');
  93. int dotIndex = input.lastIndexOf('.');
  94. if ((atIndex == -1) || (dotIndex == -1) || (atIndex >= dotIndex)) {
  95. //@todo : localize me
  96. throw new BadInputException("Error: '" + DisableHtmlTagFilter.filter(input) + "' is not a valid email value. Please try again.");
  97. }
  98. // now check for content of the string
  99. int length = input.length();
  100. char c;
  101. for (int i = 0; i < length; i++) {
  102. c = input.charAt(i);
  103. if ((c >= 'a') && (c <= 'z')) {
  104. // lower char
  105. } else if ((c >= 'A') && (c <= 'Z')) {
  106. // upper char
  107. } else if ((c >= '0') && (c <= '9')/* && (i != 0)*/) {
  108. // as of 31 Jan 2004, i relax the email checking
  109. // so that the email can start with an numeric char
  110. // hopefully it does not introduce a security bug
  111. // because this value will be inserted into sql script
  112. // numeric char
  113. } else if ( ( (c=='_') || (c=='-') || (c=='.') || (c=='@') ) && (i != 0) ) {
  114. // _ char
  115. } else {
  116. // not good char, throw an BadInputException
  117. //@todo : localize me
  118. throw new BadInputException(input + " is not a valid email. Reason: character '" + c + "' is not accepted in an email.");
  119. }
  120. }// for
  121. // last check
  122. try {
  123. new javax.mail.internet.InternetAddress(input);
  124. } catch (Exception ex) {
  125. log.error("Error when running checkGoodEmail", ex);
  126. throw new BadInputException("Assertion: don't want to occur in Util.checkGoodEmail");
  127. }
  128. }
  129. /**
  130. * NOTE: param to, cc, bcc cannot be all empty. At least one must have a valid value
  131. * @param from : must be a valid email. However, if this param is null,
  132. * then the default mail in config file will be use
  133. * @param to : can be null
  134. * @param cc : can be null
  135. * @param bcc: can be null
  136. * @param subject
  137. * @param message
  138. * @throws MessagingException
  139. * @throws BadInputException
  140. */
  141. public static void sendMail(String from, String to, String cc, String bcc, String subject, String message, boolean sendAsHTML)
  142. throws MessagingException, BadInputException, UnsupportedEncodingException {
  143. MailMessageStruct mailItem = new MailMessageStruct();
  144. mailItem.setFrom(from);
  145. mailItem.setTo(to);
  146. mailItem.setCc(cc);
  147. mailItem.setBcc(bcc);
  148. mailItem.setSubject(subject);
  149. mailItem.setMessage(message);
  150. mailItem.setSendAsHtml(sendAsHTML);
  151. sendMail(mailItem);
  152. }
  153. public static void sendMail(InternetAddress from, String to, String cc, String bcc, String subject, String message, boolean sendAsHTML)
  154. throws MessagingException, BadInputException, UnsupportedEncodingException {
  155. MailMessageStruct mailItem = new MailMessageStruct();
  156. mailItem.setFrom(from.getAddress());
  157. mailItem.setFromDisplayName(from.getPersonal());
  158. mailItem.setTo(to);
  159. mailItem.setCc(cc);
  160. mailItem.setBcc(bcc);
  161. mailItem.setSubject(subject);
  162. mailItem.setMessage(message);
  163. mailItem.setSendAsHtml(sendAsHTML);
  164. sendMail(mailItem);
  165. }
  166. public static void sendMail(MailMessageStruct mailItem)
  167. throws MessagingException, BadInputException, UnsupportedEncodingException {
  168. ArrayList mailList = new ArrayList(1);
  169. mailList.add(mailItem);
  170. try {
  171. sendMail(mailList);
  172. } catch (MessagingException mex) {
  173. log.error("MessagingException has occured.", mex);
  174. log.debug("MessagingException has occured. Detail info:");
  175. log.debug("from = " + mailItem.getFrom());
  176. log.debug("to = " + mailItem.getTo());
  177. log.debug("cc = " + mailItem.getCc());
  178. log.debug("bcc = " + mailItem.getBcc());
  179. log.debug("subject = " + mailItem.getSubject());
  180. log.debug("message = " + mailItem.getMessage());
  181. throw mex;// this may look redundant, but it is not :-)
  182. }
  183. }
  184. public static void sendMail(Collection mailStructCollection)
  185. throws MessagingException, BadInputException, UnsupportedEncodingException {
  186. Session session = null;
  187. Transport transport = null;
  188. int totalEmails = mailStructCollection.size();
  189. int count = 0;
  190. int sendFailedExceptionCount = 0;
  191. String server = "";
  192. String userName = "";
  193. String password = "";
  194. int port = 25;
  195. MailConfig config = MVNCoreConfig.getSendMailConfig();
  196. boolean useMailsource = config.useMailSource();
  197. boolean useEmbededMailServer = config.useEmbededSMTPMailServer();
  198. String smtp = "smtp";
  199. if (config.isUseSecureConnection()) {
  200. smtp = "smtps";
  201. }
  202. try {
  203. for (Iterator iter = mailStructCollection.iterator(); iter.hasNext(); ) {
  204. if ((transport == null) || (session == null)) {
  205. if (useEmbededMailServer) {
  206. session = Session.getDefaultInstance(new Properties());
  207. } else if (useMailsource) {
  208. try {
  209. InitialContext ic = new InitialContext();
  210. // mailSourceName = "java:comp/env/mail/mailSession";
  211. String mailSourceName = config.getSourceName();
  212. log.debug("MailUtil : use mailsource = " + mailSourceName);
  213. if (mailSourceName.startsWith("mail:")) {
  214. session = (Session) ic.lookup(mailSourceName);
  215. } else {
  216. session = (Session) ic.lookup("java:comp/env/" + mailSourceName);
  217. }
  218. transport = session.getTransport(smtp);
  219. } catch (NamingException e) {
  220. log.error("Cannot get Mail session", e);
  221. throw new MessagingException("Cannot get the mail session from JNDI. Send mail failed.");
  222. }
  223. } else {// does not use datasourse
  224. // TODO the variable props could be cached outside of the loop
  225. Properties props = new Properties();
  226. server = config.getMailServer();
  227. port = config.getPort();
  228. userName = config.getUserName();
  229. password = config.getPassword();
  230. // Local host name used in the SMTP HELO or EHLO command
  231. try {
  232. if (InetAddress.getLocalHost().getHostName() == null) {
  233. props.put("mail." + smtp + ".localhost", server);
  234. }
  235. } catch (UnknownHostException e) {
  236. props.put("mail." + smtp + ".localhost", server);
  237. }
  238. props.put("mail." + smtp + ".host", server);
  239. props.put("mail." + smtp + ".port", String.valueOf(port));
  240. if ((userName != null) && (userName.length() > 0)) {
  241. props.put("mail." + smtp + ".auth", "true");
  242. }
  243. props.put("mail.debug", "true");
  244. session = Session.getDefaultInstance(props, null);
  245. transport = session.getTransport(smtp);
  246. }// end of does not use datasource
  247. if (useEmbededMailServer == false) {
  248. if ((userName != null) && (userName.length() > 0)) {
  249. transport.connect(server, userName, password);
  250. } else {
  251. transport.connect();
  252. }
  253. }
  254. }
  255. MailMessageStruct mailItem = (MailMessageStruct)iter.next();
  256. String from = mailItem.getFrom();
  257. String fromDisplayName = mailItem.getFromDisplayName();
  258. String to = mailItem.getTo();
  259. String cc = mailItem.getCc();
  260. String bcc = mailItem.getBcc();
  261. String subject = mailItem.getSubject();
  262. String message = mailItem.getMessage();
  263. if (from == null) {
  264. from = MVNCoreConfig.getDefaultMailFrom();
  265. }
  266. try {
  267. // this will also check for email error
  268. checkGoodEmail(from);
  269. InternetAddress fromAddress = null;
  270. if (fromDisplayName == null) {
  271. fromAddress = new InternetAddress(from);
  272. } else {
  273. fromAddress = new InternetAddress(from, fromDisplayName);
  274. }
  275. InternetAddress[] toAddress = getInternetAddressEmails(to);
  276. InternetAddress[] ccAddress = getInternetAddressEmails(cc);
  277. InternetAddress[] bccAddress = getInternetAddressEmails(bcc);
  278. if ((toAddress == null) && (ccAddress == null) && (bccAddress == null)) {
  279. //@todo : localize me
  280. throw new BadInputException("Cannot send mail since all To, Cc, Bcc addresses are empty.");
  281. }
  282. // create a message
  283. MimeMessage msg = new MimeMessage(session);
  284. msg.setSentDate(new Date());
  285. msg.setFrom(fromAddress);
  286. if (toAddress != null) {
  287. msg.setRecipients(Message.RecipientType.TO, toAddress);
  288. }
  289. if (ccAddress != null) {
  290. msg.setRecipients(Message.RecipientType.CC, ccAddress);
  291. }
  292. if (bccAddress != null) {
  293. msg.setRecipients(Message.RecipientType.BCC, bccAddress);
  294. }
  295. if (mailItem.isSendAsHtml() == false) {
  296. //This code is use to display unicode in Subject
  297. //msg.setSubject(MimeUtility.encodeText(subject, "iso-8859-1", "Q"));
  298. //msg.setText(message);
  299. //String content = new String(message.getBytes(""), "UTF-8");
  300. msg.setSubject(subject, "UTF-8");
  301. msg.setText(message, "UTF-8");
  302. } else {
  303. //Below code is use for unicode
  304. MimeBodyPart messageBodyPart = new MimeBodyPart();
  305. msg.setSubject(subject, "UTF-8");
  306. messageBodyPart.setText(message, "UTF-8");
  307. messageBodyPart.setHeader("Content-Type", "text/html;charset=UTF-8");
  308. messageBodyPart.setHeader("Content-Transfer-Encoding", "quoted-printable");
  309. MimeMultipart multipart = new MimeMultipart("alternative");
  310. multipart.addBodyPart(messageBodyPart);
  311. msg.setContent(multipart);
  312. }
  313. msg.saveChanges();
  314. if (useEmbededMailServer) {
  315. MailQue.queMail(msg);
  316. } else {
  317. transport.sendMessage(msg, msg.getAllRecipients());
  318. }
  319. if (useEmbededMailServer == false) {
  320. // now check if sent 100 emails, then close connection (transport)
  321. if ( ((count+1) % MAX_MESSAGES_PER_TRANSPORT) == 0 ) {
  322. try {
  323. if (transport != null) transport.close();
  324. } catch (MessagingException ex) {}
  325. transport = null;
  326. session = null;
  327. }
  328. }
  329. } catch (SendFailedException ex) {
  330. sendFailedExceptionCount++;
  331. log.error("SendFailedException has occured.", ex);
  332. log.warn("SendFailedException has occured. Detail info:");
  333. log.warn("from = " + from);
  334. log.warn("to = " + to);
  335. log.warn("cc = " + cc);
  336. log.warn("bcc = " + bcc);
  337. log.warn("subject = " + subject);
  338. log.info("message = " + message);
  339. if ((totalEmails != 1) && (sendFailedExceptionCount > 10)) {
  340. throw ex;// this may look redundant, but it is not :-)
  341. }
  342. } catch (MessagingException mex) {
  343. log.error("MessagingException has occured.", mex);
  344. log.warn("MessagingException has occured. Detail info:");
  345. log.warn("from = " + from);
  346. log.warn("to = " + to);
  347. log.warn("cc = " + cc);
  348. log.warn("bcc = " + bcc);
  349. log.warn("subject = " + subject);
  350. log.info("message = " + message);
  351. throw mex;// this may look redundant, but it is not :-)
  352. }
  353. // we increase count when send successfully
  354. count++;
  355. }//for
  356. } finally {
  357. try {
  358. if (transport != null) transport.close();
  359. } catch (MessagingException ex) { }
  360. if (totalEmails != 1) {
  361. String sendMailMethod = "";
  362. if (useEmbededMailServer) {
  363. sendMailMethod = "Embeded SMTP Server";
  364. } else if (useMailsource) {
  365. sendMailMethod = "Mail Source";
  366. } else {
  367. sendMailMethod = "External SMTP Server";
  368. }
  369. log.info("sendMail: totalEmails = " + totalEmails + " sent count = " + count + " using " + sendMailMethod);
  370. }
  371. }
  372. }
  373. /**
  374. * This method trim the email variable, so if it contains only spaces,
  375. * then it will be empty string, then we have 0 token :-)
  376. * The returned value is never null
  377. */
  378. public static String[] getEmails(String email) throws BadInputException {
  379. if (email == null) email = "";
  380. email = email.trim();// very important
  381. email = email.replace(',', ';');// replace all occurrence of ',' to ';'
  382. StringTokenizer t = new StringTokenizer(email, ";");
  383. String[] ret = new String[t.countTokens()];
  384. int index = 0;
  385. while(t.hasMoreTokens()) {
  386. String mail = t.nextToken().trim();
  387. checkGoodEmail(mail);
  388. ret[index] = mail;
  389. //log.debug(ret[index]);
  390. index++;
  391. }
  392. return ret;
  393. }
  394. public static String[] getEmails(String to, String cc, String bcc) throws BadInputException {
  395. String[] toMail = getEmails(to);
  396. String[] ccMail = getEmails(cc);
  397. String[] bccMail= getEmails(bcc);
  398. String[] ret = new String[toMail.length + ccMail.length + bccMail.length];
  399. int index = 0;
  400. for (int i = 0; i < toMail.length; i++) {
  401. ret[index] = toMail[i];
  402. index++;
  403. }
  404. for (int i = 0; i < ccMail.length; i++) {
  405. ret[index] = ccMail[i];
  406. index++;
  407. }
  408. for (int i = 0; i < bccMail.length; i++) {
  409. ret[index] = bccMail[i];
  410. index++;
  411. }
  412. return ret;
  413. }
  414. /**
  415. * This method will return null if there is not any email
  416. *
  417. * @param email
  418. * @return
  419. * @throws BadInputException
  420. * @throws AddressException
  421. */
  422. private static InternetAddress[] getInternetAddressEmails(String email)
  423. throws BadInputException, AddressException {
  424. String[] mails = getEmails(email);
  425. if (mails.length == 0) return null;// must return null, not empty array
  426. //log.debug("to = " + mails);
  427. InternetAddress[] address = new InternetAddress[mails.length];
  428. for (int i = 0; i < mails.length; i++) {
  429. address[i] = new InternetAddress(mails[i]);
  430. //log.debug("to each element = " + mails[i]);
  431. }
  432. return address;
  433. }
  434. public static MailMessageStruct[] receiveEmail(String popServer, String popUser, String popPassword) {
  435. Store store = null;
  436. Folder folder = null;
  437. MailMessageStruct[] mailMessageStructsArray = null;
  438. String provider = "pop3";
  439. if (MVNCoreConfig.getReceiveMailConfig().isUseSecureConnection()) {
  440. provider = "pop3s";
  441. }
  442. try {
  443. // -- Get hold of the default session --
  444. Properties props = new Properties();
  445. props.put("mail.pop3.port", String.valueOf(MVNCoreConfig.getReceiveMailConfig().getPort()));
  446. Session session = Session.getDefaultInstance(props, null);
  447. session.setDebug(true);
  448. // -- Get hold of a POP3 message store, and connect to it --
  449. store = session.getStore(provider);
  450. store.connect(popServer, popUser, popPassword);
  451. // -- Try to get hold of the default folder --
  452. folder = store.getDefaultFolder();
  453. if (folder == null) {
  454. throw new IOException("No default folder");
  455. }
  456. // -- ...and its INBOX --
  457. folder = folder.getFolder("INBOX");
  458. if (folder == null) {
  459. throw new IOException("No POP3 INBOX");
  460. }
  461. // -- Open the folder for read write --
  462. folder.open(Folder.READ_WRITE);
  463. // -- Get the message wrappers and process them --
  464. Message[] msgs = folder.getMessages();
  465. mailMessageStructsArray = new MailMessageStruct [msgs.length];
  466. for (int msgNum = 0; msgNum < msgs.length; msgNum++) {
  467. mailMessageStructsArray[msgNum] = createMessageStructFromMessage(msgs[msgNum]);
  468. msgs[msgNum].setFlag(Flag.DELETED, true);
  469. }
  470. return mailMessageStructsArray;
  471. } catch (Exception ex) {
  472. log.error("Error when receiving email.", ex);
  473. } finally {
  474. if (folder != null) {
  475. try {
  476. folder.close(true);
  477. } catch (MessagingException e) {
  478. log.error("Cannot close POP Folder.", e);
  479. }
  480. }
  481. if (store != null) {
  482. try {
  483. store.close();
  484. } catch (MessagingException e) {
  485. log.error("Cannot close POP Store.", e);
  486. }
  487. }
  488. }
  489. return new MailMessageStruct[0];
  490. }
  491. private static MailMessageStruct createMessageStructFromMessage(Message message)
  492. throws MessagingException, IOException {
  493. MailMessageStruct mailMessageStruct = new MailMessageStruct();
  494. String fromEmailString = null;
  495. Address[] from = message.getFrom();
  496. if (from != null) {
  497. Address fromEmail = from[0];
  498. fromEmailString = ((InternetAddress)fromEmail).getAddress();
  499. }
  500. String subject = message.getSubject();
  501. Part messagePart = message;
  502. Object content = messagePart.getContent();
  503. // -- or its first body part if it is a multipart message --
  504. if (content instanceof Multipart) {
  505. messagePart = ((Multipart)content).getBodyPart(0);
  506. }
  507. // -- Get the content type --
  508. String contentType = (String)messagePart.getContent();
  509. mailMessageStruct.setFrom(fromEmailString);
  510. mailMessageStruct.setSubject(subject);
  511. mailMessageStruct.setMessage(contentType);
  512. return mailMessageStruct;
  513. }
  514. }