You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

MailMessageTest.java 24 kB

7 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. package org.apache.tools.mail;
  19. import static org.junit.Assert.assertEquals;
  20. import static org.junit.Assert.assertFalse;
  21. import java.io.BufferedReader;
  22. import java.io.BufferedWriter;
  23. import java.io.ByteArrayOutputStream;
  24. import java.io.IOException;
  25. import java.io.InputStreamReader;
  26. import java.io.OutputStreamWriter;
  27. import java.io.PrintStream;
  28. import java.net.InetAddress;
  29. import java.net.ServerSocket;
  30. import java.net.Socket;
  31. import java.util.Vector;
  32. import org.apache.tools.ant.BuildException;
  33. import org.junit.AssumptionViolatedException;
  34. import org.junit.Before;
  35. import org.junit.Test;
  36. /**
  37. * JUnit testcases for org.apache.tools.mail.MailMessage.
  38. *
  39. * @since Ant 1.6
  40. */
  41. public class MailMessageTest {
  42. // 27224 = magic (a random port which is unlikely to be in use)
  43. private static int TEST_PORT = 27224;
  44. private String local = null;
  45. @Before
  46. public void setUp() {
  47. try {
  48. local = InetAddress.getLocalHost().getHostName();
  49. } catch (java.net.UnknownHostException uhe) {
  50. // ignore
  51. }
  52. }
  53. /**
  54. * Test an example that is similar to the one given in the API
  55. * If this testcase takes >90s to complete, it is very likely that
  56. * the two threads are blocked waiting for each other and Thread.join()
  57. * timed out.
  58. * @throws InterruptedException if something goes wrong
  59. */
  60. @Test
  61. public void testAPIExample() throws InterruptedException {
  62. final int port = TEST_PORT + 1;
  63. ServerThread testMailServer = new ServerThread(port);
  64. Thread server = new Thread(testMailServer);
  65. server.start();
  66. ClientThread testMailClient = new ClientThread(port);
  67. testMailClient.from("Mail Message <EmailTaskTest@ant.apache.org>");
  68. testMailClient.to("to@you.com");
  69. testMailClient.cc("cc1@you.com");
  70. testMailClient.cc("cc2@you.com");
  71. testMailClient.bcc("bcc@you.com");
  72. testMailClient.setSubject("Test subject");
  73. testMailClient.setMessage("test line 1\n"
  74. + "test line 2");
  75. Thread client = new Thread(testMailClient);
  76. client.start();
  77. server.join(60 * 1000); // 60s
  78. client.join(30 * 1000); // a further 30s
  79. String result = testMailServer.getResult();
  80. String expectedResult = "220 test SMTP EmailTaskTest\r\n"
  81. + "HELO " + local + "\r\n"
  82. + "250 " + local + " Hello " + local + " [127.0.0.1], pleased to meet you\r\n"
  83. + "MAIL FROM: <EmailTaskTest@ant.apache.org>\r\n"
  84. + "250\r\n"
  85. + "RCPT TO: <to@you.com>\r\n"
  86. + "250\r\n"
  87. + "RCPT TO: <cc1@you.com>\r\n"
  88. + "250\r\n"
  89. + "RCPT TO: <cc2@you.com>\r\n"
  90. + "250\r\n"
  91. + "RCPT TO: <bcc@you.com>\r\n"
  92. + "250\r\n"
  93. + "DATA\r\n"
  94. + "354\r\n"
  95. + "Subject: Test subject\r\n" + "From: Mail Message <EmailTaskTest@ant.apache.org>\r\n"
  96. + "To: to@you.com\r\n"
  97. + "Cc: cc1@you.com, cc2@you.com\r\n"
  98. + "X-Mailer: org.apache.tools.mail.MailMessage (ant.apache.org)\r\n"
  99. + "\r\n"
  100. + "test line 1\r\n"
  101. + "test line 2\r\n"
  102. + "\r\n"
  103. + ".\r\n"
  104. + "250\r\n"
  105. + "QUIT\r\n"
  106. + "221\r\n";
  107. assertEquals(expectedResult, result); // order of headers cannot be guaranteed
  108. assertFalse(testMailClient.getFailMessage(), testMailClient.isFailed());
  109. }
  110. /**
  111. * Test a MailMessage with no cc or bcc lines
  112. * @throws InterruptedException if something goes wrong
  113. */
  114. @Test
  115. public void testToOnly() throws InterruptedException {
  116. final int port = TEST_PORT + 2;
  117. ServerThread testMailServer = new ServerThread(port);
  118. Thread server = new Thread(testMailServer);
  119. server.start();
  120. ClientThread testMailClient = new ClientThread(port);
  121. testMailClient.from("Mail Message <EmailTaskTest@ant.apache.org>");
  122. testMailClient.to("to@you.com");
  123. testMailClient.setSubject("Test subject");
  124. testMailClient.setMessage("test line 1\n" + "test line 2");
  125. Thread client = new Thread(testMailClient);
  126. client.start();
  127. server.join(60 * 1000); // 60s
  128. client.join(30 * 1000); // a further 30s
  129. String result = testMailServer.getResult();
  130. String expectedResult = "220 test SMTP EmailTaskTest\r\n"
  131. + "HELO " + local + "\r\n"
  132. + "250 " + local + " Hello " + local + " [127.0.0.1], pleased to meet you\r\n"
  133. + "MAIL FROM: <EmailTaskTest@ant.apache.org>\r\n"
  134. + "250\r\n"
  135. + "RCPT TO: <to@you.com>\r\n"
  136. + "250\r\n"
  137. + "DATA\r\n"
  138. + "354\r\n"
  139. + "Subject: Test subject\r\n"
  140. + "From: Mail Message <EmailTaskTest@ant.apache.org>\r\n"
  141. + "To: to@you.com\r\n"
  142. + "X-Mailer: org.apache.tools.mail.MailMessage (ant.apache.org)\r\n"
  143. + "\r\n"
  144. + "test line 1\r\n"
  145. + "test line 2\r\n"
  146. + "\r\n"
  147. + ".\r\n"
  148. + "250\r\n"
  149. + "QUIT\r\n"
  150. + "221\r\n";
  151. assertEquals(expectedResult, result); // order of headers cannot be guaranteed
  152. assertFalse(testMailClient.getFailMessage(), testMailClient.isFailed());
  153. }
  154. /**
  155. * Test a MailMessage with no to or bcc lines
  156. * @throws InterruptedException if something goes wrong
  157. */
  158. @Test
  159. public void testCcOnly() throws InterruptedException {
  160. final int port = TEST_PORT + 3;
  161. ServerThread testMailServer = new ServerThread(port);
  162. Thread server = new Thread(testMailServer);
  163. server.start();
  164. ClientThread testMailClient = new ClientThread(port);
  165. testMailClient.from("Mail Message <EmailTaskTest@ant.apache.org>");
  166. testMailClient.cc("cc@you.com");
  167. testMailClient.setSubject("Test subject");
  168. testMailClient.setMessage("test line 1\n" + "test line 2");
  169. Thread client = new Thread(testMailClient);
  170. client.start();
  171. server.join(60 * 1000); // 60s
  172. client.join(30 * 1000); // a further 30s
  173. String result = testMailServer.getResult();
  174. String expectedResult = "220 test SMTP EmailTaskTest\r\n"
  175. + "HELO " + local + "\r\n"
  176. + "250 " + local + " Hello " + local + " [127.0.0.1], pleased to meet you\r\n"
  177. + "MAIL FROM: <EmailTaskTest@ant.apache.org>\r\n"
  178. + "250\r\n"
  179. + "RCPT TO: <cc@you.com>\r\n"
  180. + "250\r\n"
  181. + "DATA\r\n"
  182. + "354\r\n"
  183. + "Subject: Test subject\r\n"
  184. + "From: Mail Message <EmailTaskTest@ant.apache.org>\r\n"
  185. + "Cc: cc@you.com\r\n"
  186. + "X-Mailer: org.apache.tools.mail.MailMessage (ant.apache.org)\r\n"
  187. + "\r\n"
  188. + "test line 1\r\n"
  189. + "test line 2\r\n"
  190. + "\r\n"
  191. + ".\r\n"
  192. + "250\r\n"
  193. + "QUIT\r\n"
  194. + "221\r\n";
  195. assertEquals(expectedResult, result);
  196. assertFalse(testMailClient.getFailMessage(), testMailClient.isFailed());
  197. }
  198. /**
  199. * Test a MailMessage with no to or cc lines
  200. * @throws InterruptedException if something goes wrong
  201. */
  202. @Test
  203. public void testBccOnly() throws InterruptedException {
  204. final int port = TEST_PORT + 4;
  205. ServerThread testMailServer = new ServerThread(port);
  206. Thread server = new Thread(testMailServer);
  207. server.start();
  208. ClientThread testMailClient = new ClientThread(port);
  209. testMailClient.from("Mail Message <EmailTaskTest@ant.apache.org>");
  210. testMailClient.bcc("bcc@you.com");
  211. testMailClient.setSubject("Test subject");
  212. testMailClient.setMessage("test line 1\n" + "test line 2");
  213. Thread client = new Thread(testMailClient);
  214. client.start();
  215. server.join(60 * 1000); // 60s
  216. client.join(30 * 1000); // a further 30s
  217. String result = testMailServer.getResult();
  218. String expectedResult = "220 test SMTP EmailTaskTest\r\n"
  219. + "HELO " + local + "\r\n"
  220. + "250 " + local + " Hello " + local + " [127.0.0.1], pleased to meet you\r\n"
  221. + "MAIL FROM: <EmailTaskTest@ant.apache.org>\r\n"
  222. + "250\r\n"
  223. + "RCPT TO: <bcc@you.com>\r\n"
  224. + "250\r\n"
  225. + "DATA\r\n"
  226. + "354\r\n"
  227. + "Subject: Test subject\r\n"
  228. + "From: Mail Message <EmailTaskTest@ant.apache.org>\r\n"
  229. + "X-Mailer: org.apache.tools.mail.MailMessage (ant.apache.org)\r\n"
  230. + "\r\n"
  231. + "test line 1\r\n"
  232. + "test line 2\r\n"
  233. + "\r\n"
  234. + ".\r\n"
  235. + "250\r\n"
  236. + "QUIT\r\n"
  237. + "221\r\n";
  238. assertEquals(expectedResult, result);
  239. assertFalse(testMailClient.getFailMessage(), testMailClient.isFailed());
  240. }
  241. /**
  242. * Test a MailMessage with no subject line
  243. * Subject is an optional field (RFC 822 s4.1)
  244. * @throws InterruptedException if something goes wrong
  245. */
  246. @Test
  247. public void testNoSubject() throws InterruptedException {
  248. final int port = TEST_PORT + 5;
  249. ServerThread testMailServer = new ServerThread(port);
  250. Thread server = new Thread(testMailServer);
  251. server.start();
  252. ClientThread testMailClient = new ClientThread(port);
  253. testMailClient.from("Mail Message <EmailTaskTest@ant.apache.org>");
  254. testMailClient.to("to@you.com");
  255. testMailClient.setMessage("test line 1\n" + "test line 2");
  256. Thread client = new Thread(testMailClient);
  257. client.start();
  258. server.join(60 * 1000); // 60s
  259. client.join(30 * 1000); // a further 30s
  260. String result = testMailServer.getResult();
  261. String expectedResult = "220 test SMTP EmailTaskTest\r\n"
  262. + "HELO " + local + "\r\n"
  263. + "250 " + local + " Hello " + local + " [127.0.0.1], pleased to meet you\r\n"
  264. + "MAIL FROM: <EmailTaskTest@ant.apache.org>\r\n"
  265. + "250\r\n"
  266. + "RCPT TO: <to@you.com>\r\n"
  267. + "250\r\n"
  268. + "DATA\r\n"
  269. + "354\r\n"
  270. + "From: Mail Message <EmailTaskTest@ant.apache.org>\r\n"
  271. + "To: to@you.com\r\n"
  272. + "X-Mailer: org.apache.tools.mail.MailMessage (ant.apache.org)\r\n"
  273. + "\r\n"
  274. + "test line 1\r\n"
  275. + "test line 2\r\n"
  276. + "\r\n"
  277. + ".\r\n"
  278. + "250\r\n"
  279. + "QUIT\r\n"
  280. + "221\r\n";
  281. assertEquals(expectedResult, result);
  282. assertFalse(testMailClient.getFailMessage(), testMailClient.isFailed());
  283. }
  284. /**
  285. * Test a MailMessage with empty body message
  286. * @throws InterruptedException if something goes wrong
  287. */
  288. @Test
  289. public void testEmptyBody() throws InterruptedException {
  290. final int port = TEST_PORT + 6;
  291. ServerThread testMailServer = new ServerThread(port);
  292. Thread server = new Thread(testMailServer);
  293. server.start();
  294. ClientThread testMailClient = new ClientThread(port);
  295. testMailClient.from("Mail Message <EmailTaskTest@ant.apache.org>");
  296. testMailClient.to("to@you.com");
  297. testMailClient.setSubject("Test subject");
  298. testMailClient.setMessage("");
  299. Thread client = new Thread(testMailClient);
  300. client.start();
  301. server.join(60 * 1000); // 60s
  302. client.join(30 * 1000); // a further 30s
  303. String result = testMailServer.getResult();
  304. String expectedResult = "220 test SMTP EmailTaskTest\r\n"
  305. + "HELO " + local + "\r\n"
  306. + "250 " + local + " Hello " + local + " [127.0.0.1], pleased to meet you\r\n"
  307. + "MAIL FROM: <EmailTaskTest@ant.apache.org>\r\n"
  308. + "250\r\n"
  309. + "RCPT TO: <to@you.com>\r\n"
  310. + "250\r\n"
  311. + "DATA\r\n"
  312. + "354\r\n"
  313. + "Subject: Test subject\r\n"
  314. + "From: Mail Message <EmailTaskTest@ant.apache.org>\r\n"
  315. + "To: to@you.com\r\n"
  316. + "X-Mailer: org.apache.tools.mail.MailMessage (ant.apache.org)\r\n"
  317. + "\r\n"
  318. + "\r\n"
  319. + "\r\n"
  320. + ".\r\n"
  321. + "250\r\n"
  322. + "QUIT\r\n"
  323. + "221\r\n";
  324. assertEquals(expectedResult, result);
  325. assertFalse(testMailClient.getFailMessage(), testMailClient.isFailed());
  326. }
  327. /**
  328. * Test a MailMessage with US-ASCII character set
  329. * The next four testcase can be kinda hard to debug as Ant will often
  330. * print the junit failure in US-ASCII.
  331. * @throws InterruptedException if something goes wrong
  332. */
  333. @Test
  334. public void testAsciiCharset() throws InterruptedException {
  335. final int port = TEST_PORT + 7;
  336. ServerThread testMailServer = new ServerThread(port);
  337. Thread server = new Thread(testMailServer);
  338. server.start();
  339. ClientThread testMailClient = new ClientThread(port);
  340. testMailClient.from("Mail Message <EmailTaskTest@ant.apache.org>");
  341. testMailClient.to("Ceki G\u00fclc\u00fc <abuse@mail-abuse.org>");
  342. testMailClient.setSubject("Test subject");
  343. testMailClient.setMessage("");
  344. Thread client = new Thread(testMailClient);
  345. client.start();
  346. server.join(60 * 1000); // 60s
  347. client.join(30 * 1000); // a further 30s
  348. String result = testMailServer.getResult();
  349. String expectedResult = "220 test SMTP EmailTaskTest\r\n"
  350. + "HELO " + local + "\r\n"
  351. + "250 " + local + " Hello " + local + " [127.0.0.1], pleased to meet you\r\n"
  352. + "MAIL FROM: <EmailTaskTest@ant.apache.org>\r\n"
  353. + "250\r\n"
  354. + "RCPT TO: <abuse@mail-abuse.org>\r\n"
  355. + "250\r\n"
  356. + "DATA\r\n"
  357. + "354\r\n"
  358. + "Subject: Test subject\r\n"
  359. + "From: Mail Message <EmailTaskTest@ant.apache.org>\r\n"
  360. + "To: Ceki G\u00fclc\u00fc <abuse@mail-abuse.org>\r\n"
  361. + "X-Mailer: org.apache.tools.mail.MailMessage (ant.apache.org)\r\n"
  362. + "\r\n"
  363. + "\r\n"
  364. + "\r\n"
  365. + ".\r\n"
  366. + "250\r\n"
  367. + "QUIT\r\n"
  368. + "221\r\n";
  369. ByteArrayOutputStream baos1 = new ByteArrayOutputStream();
  370. ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
  371. PrintStream bos1 = new PrintStream(baos1, true);
  372. PrintStream bos2 = new PrintStream(baos2, true);
  373. bos1.print(expectedResult);
  374. bos2.print(result);
  375. assertEquals("baos1 and baos2 should be the same in testAsciiCharset()",
  376. baos1.toString(), baos2.toString()); // order of headers cannot be guaranteed
  377. assertFalse(testMailClient.getFailMessage(), testMailClient.isFailed());
  378. }
  379. /**
  380. * A private test class that pretends to be a mail transfer agent
  381. */
  382. private class ServerThread implements Runnable {
  383. private final int port;
  384. private StringBuilder sb = null;
  385. private boolean loop = false;
  386. ServerSocket ssock = null;
  387. Socket sock = null;
  388. BufferedWriter out = null;
  389. BufferedReader in = null;
  390. private boolean data = false; // state engine: false=envelope, true=message
  391. ServerThread(int port) {
  392. this.port = port;
  393. }
  394. public void run() {
  395. try {
  396. ssock = new ServerSocket(port);
  397. sock = ssock.accept(); // wait for connection
  398. in = new BufferedReader(new InputStreamReader(
  399. sock.getInputStream()));
  400. out = new BufferedWriter(new OutputStreamWriter(
  401. sock.getOutputStream()));
  402. sb = new StringBuilder();
  403. send("220 test SMTP EmailTaskTest\r\n");
  404. loop = true;
  405. while (loop) {
  406. String response = in.readLine();
  407. if (response == null) {
  408. loop = false;
  409. break;
  410. }
  411. sb.append(response).append("\r\n");
  412. if (!data && response.startsWith("HELO")) {
  413. send("250 " + local + " Hello " + local + " "
  414. + "[127.0.0.1], pleased to meet you\r\n");
  415. } else if (!data && response.startsWith("MAIL")) {
  416. send("250\r\n");
  417. } else if (!data && response.startsWith("RCPT")) {
  418. send("250\r\n");
  419. } else if (!data && response.startsWith("DATA")) {
  420. send("354\r\n");
  421. data = true;
  422. } else if (data && response.equals(".")) {
  423. send("250\r\n");
  424. data = false;
  425. } else if (!data && response.startsWith("QUIT")) {
  426. send("221\r\n");
  427. loop = false;
  428. } else if (!data) {
  429. //throw new IllegalStateException("Command unrecognized: "
  430. // + response);
  431. send("500 5.5.1 Command unrecognized: \""
  432. + response + "\"\r\n");
  433. loop = false;
  434. } else {
  435. // sb.append(response + "\r\n");
  436. }
  437. } // while
  438. } catch (IOException ioe) {
  439. throw new BuildException(ioe);
  440. } finally {
  441. disconnect();
  442. }
  443. }
  444. private void send(String retmsg) throws IOException {
  445. out.write(retmsg);
  446. out.flush();
  447. sb.append(retmsg);
  448. }
  449. private void disconnect() {
  450. if (out != null) {
  451. try {
  452. out.flush();
  453. out.close();
  454. out = null;
  455. } catch (IOException e) {
  456. // ignore
  457. }
  458. }
  459. if (in != null) {
  460. try {
  461. in.close();
  462. in = null;
  463. } catch (IOException e) {
  464. // ignore
  465. }
  466. }
  467. if (sock != null) {
  468. try {
  469. sock.close();
  470. sock = null;
  471. } catch (IOException e) {
  472. // ignore
  473. }
  474. }
  475. if (ssock != null) {
  476. try {
  477. ssock.close();
  478. ssock = null;
  479. } catch (IOException e) {
  480. // ignore
  481. }
  482. }
  483. }
  484. public synchronized String getResult() {
  485. loop = false;
  486. return sb.toString();
  487. }
  488. }
  489. /**
  490. * A private test class that wraps MailMessage
  491. */
  492. private class ClientThread implements Runnable {
  493. private final int port;
  494. private MailMessage msg;
  495. private boolean fail = false;
  496. private String failMessage = null;
  497. protected String from = null;
  498. protected String subject = null;
  499. protected String message = null;
  500. protected Vector<String> replyToList = new Vector<>();
  501. protected Vector<String> toList = new Vector<>();
  502. protected Vector<String> ccList = new Vector<>();
  503. protected Vector<String> bccList = new Vector<>();
  504. ClientThread(int port) {
  505. this.port = port;
  506. }
  507. public void run() {
  508. for (int i = 9; i > 0; i--) {
  509. try {
  510. msg = new MailMessage("localhost", port);
  511. } catch (java.net.ConnectException ce) {
  512. try {
  513. Thread.sleep(10 * 1000);
  514. } catch (InterruptedException ie) {
  515. throw new AssumptionViolatedException("Thread interrupted", ie);
  516. }
  517. } catch (IOException ioe) {
  518. fail = true;
  519. failMessage = "IOException: " + ioe;
  520. return;
  521. }
  522. if (msg != null) {
  523. break;
  524. }
  525. }
  526. if (msg == null) {
  527. fail = true;
  528. failMessage = "java.net.ConnectException: Connection refused";
  529. return;
  530. }
  531. try {
  532. msg.from(from);
  533. replyToList.forEach(e -> msg.replyto(e));
  534. for (String e : toList) {
  535. msg.to(e);
  536. }
  537. for (String e : ccList) {
  538. msg.cc(e);
  539. }
  540. for (String e : bccList) {
  541. msg.bcc(e);
  542. }
  543. if (subject != null) {
  544. msg.setSubject(subject);
  545. }
  546. if (message != null) {
  547. PrintStream out = msg.getPrintStream();
  548. out.println(message);
  549. }
  550. msg.sendAndClose();
  551. } catch (IOException ioe) {
  552. fail = true;
  553. failMessage = "IOException: " + ioe;
  554. }
  555. }
  556. public boolean isFailed() {
  557. return fail;
  558. }
  559. public String getFailMessage() {
  560. return failMessage;
  561. }
  562. @SuppressWarnings("unused")
  563. public void replyTo(String replyTo) {
  564. replyToList.add(replyTo);
  565. }
  566. public void to(String to) {
  567. toList.add(to);
  568. }
  569. public void cc(String cc) {
  570. ccList.add(cc);
  571. }
  572. public void bcc(String bcc) {
  573. bccList.add(bcc);
  574. }
  575. public void setSubject(String subject) {
  576. this.subject = subject;
  577. }
  578. public void from(String from) {
  579. this.from = from;
  580. }
  581. public void setMessage(String message) {
  582. this.message = message;
  583. }
  584. }
  585. }