|
In this section, we show you a practical example of socket programming: a program that sends e-mail to a remote site. To send e-mail, you make a socket connection to port 25, the SMTP port. SMTP is the Simple Mail Transport Protocol that describes the format for e-mail messages. You can connect to any server that runs an SMTP service. On UNIX machines, that service is typically implemented by the sendmail daemon. However, the server must be willing to accept your request. It used to be that sendmail servers were routinely willing to route e-mail from anyone, but in these days of spam floods, most servers now have built-in checks and accept requests only from users, domains, or IP address ranges that they trust. Once you are connected to the server, send a mail header (in the SMTP format, which is easy to generate), followed by the mail message. Here are the details:
The SMTP specification (RFC 821) states that lines must be terminated with \r followed by \n. Most SMTP servers do not check the veracity of the informationyou may be able to supply any sender you like. (Keep this in mind the next time you get an e-mail message from president@whitehouse.gov inviting you to a black-tie affair on the front lawn. Anyone could have connected to an SMTP server and created a fake message.) The program in Example 3-4 is a simple e-mail program. As you can see in Figure 3-6, you type in the sender, recipient, mail message, and SMTP server. Then, click the Send button, and your message is sent. Figure 3-6. The MailTest programThe program simply sends the sequence of commands that we just discussed. It displays the commands that it sends to the SMTP server and the responses that it receives. Note that the communication with the mail server occurs in a separate thread so that the user interface thread is not blocked when the program tries to connect to the mail server. (See Chapter 1 for more details on threads in Swing applications.) Example 3-4. MailTest.java[View full width] 1. import java.awt.*; 2. import java.awt.event.*; 3. import java.util.*; 4. import java.net.*; 5. import java.io.*; 6. import javax.swing.*; 7. 8. /** 9. This program shows how to use sockets to send plain text 10. mail messages. 11. */ 12. public class MailTest 13. { 14. public static void main(String[] args) 15. { 16. JFrame frame = new MailTestFrame(); 17. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 18. frame.setVisible(true); 19. } 20. } 21. 22. /** 23. The frame for the mail GUI. 24. */ 25. class MailTestFrame extends JFrame 26. { 27. public MailTestFrame() 28. { 29. setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); 30. setTitle("MailTest"); 31. 32. setLayout(new GridBagLayout()); 33. 34. // we use the GBC convenience class of Core Java Volume 1 Chapter 9 35. add(new JLabel("From:"), new GBC(0, 0).setFill(GBC.HORIZONTAL)); 36. 37. from = new JTextField(20); 38. add(from, new GBC(1, 0).setFill(GBC.HORIZONTAL).setWeight(100, 0)); 39. 40. add(new JLabel("To:"), new GBC(0, 1).setFill(GBC.HORIZONTAL)); 41. 42. to = new JTextField(20); 43. add(to, new GBC(1, 1).setFill(GBC.HORIZONTAL).setWeight(100, 0)); 44. 45. add(new JLabel("SMTP server:"), new GBC(0, 2).setFill(GBC.HORIZONTAL)); 46. 47. smtpServer = new JTextField(20); 48. add(smtpServer, new GBC(1, 2).setFill(GBC.HORIZONTAL).setWeight(100, 0)); 49. 50. message = new JTextArea(); 51. add(new JScrollPane(message), new GBC(0, 3, 2, 1).setFill(GBC.BOTH).setWeight (100, 100)); 52. 53. comm = new JTextArea(); 54. add(new JScrollPane(comm), new GBC(0, 4, 2, 1).setFill(GBC.BOTH).setWeight(100, 100)); 55. 56. JPanel buttonPanel = new JPanel(); 57. add(buttonPanel, new GBC(0, 5, 2, 1)); 58. 59. JButton sendButton = new JButton("Send"); 60. buttonPanel.add(sendButton); 61. sendButton.addActionListener(new 62. ActionListener() 63. { 64. public void actionPerformed(ActionEvent event) 65. { 66. new Thread(new 67. Runnable() 68. { 69. public void run() 70. { 71. comm.setText(""); 72. sendMail(); 73. } 74. }).start(); 75. } 76. }); 77. } 78. 79. /** 80. Sends the mail message that has been authored in the GUI. 81. */ 82. public void sendMail() 83. { 84. try 85. { 86. Socket s = new Socket(smtpServer.getText(), 25); 87. 88. InputStream inStream = s.getInputStream(); 89. OutputStream outStream = s.getOutputStream(); 90. 91. in = new Scanner(inStream); 92. out = new PrintWriter(outStream, true /* autoFlush */); 93. 94. String hostName = InetAddress.getLocalHost().getHostName(); 95. 96. receive(); 97. send("HELO " + hostName); 98. receive(); 99. send("MAIL FROM: <" + from.getText() + ">"); 100. receive(); 101. send("RCPT TO: <" + to.getText() + ">"); 102. receive(); 103. send("DATA"); 104. receive(); 105. send(message.getText()); 106. send("."); 107. receive(); 108. s.close(); 109. } 110. catch (IOException e) 111. { 112. comm.append("Error: " + e); 113. } 114. } 115. 116. /** 117. Sends a string to the socket and echoes it in the 118. comm text area. 119. @param s the string to send. 120. */ 121. public void send(String s) throws IOException 122. { 123. comm.append(s); 124. comm.append("\n"); 125. out.print(s.replaceAll("\n", "\r\n")); 126. out.print("\r\n"); 127. out.flush(); 128. } 129. 130. /** 131. Receives a string from the socket and displays it 132. in the comm text area. 133. */ 134. public void receive() throws IOException 135. { 136. if (in.hasNextLine()); 137. { 138. String line = in.nextLine(); 139. comm.append(line); 140. comm.append("\n"); 141. } 142. } 143. 144. private Scanner in; 145. private PrintWriter out; 146. private JTextField from; 147. private JTextField to; 148. private JTextField smtpServer; 149. private JTextArea message; 150. private JTextArea comm; 151. 152. public static final int DEFAULT_WIDTH = 300; 153. public static final int DEFAULT_HEIGHT = 300; 154. } |
|