/projects/ant-1.8.2/src/tests/junit/org/apache/tools/mail/MailMessageTest.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus · Java · 734 lines · 569 code · 100 blank · 65 comment · 57 complexity · 246ab6f299742251873b04d6f9b18af0 MD5 · raw file

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