(4) 发送E-mail
(四) 发送E-mail
为了发送E-mail,必须建立一个到端口25(即SMTP端口)的套接字连接。简单邮件传输协议用于描述E-mail消息的格式。
可以连接到任何一个提供SMTP服务的服务器,不过需要确定服务器是否愿意接受请求。SMTP服务器通常总是愿意发送来自任何人的E-mail,但是由于垃圾邮件泛滥,大多数服务器都内置有检查功能,它们只接受那些来自它们所信任的用户或IP地址段的请求。
一旦连接到服务器,就可以发送一个邮件报头(采用SMTP格式)。紧随其后是邮件消息。
操作的详细过程:
1.打开一个到达主机的套接字:
Socket socket = new Socket("mail.mailserver.com", 25); PrintWriter out = new PrintWriter(socket.getOutputStream());
2.发送以下信息到输出流
HELO sending host
MAIL FROM: <sender e-mail address>
RCPT TO: <recipient e-mail address>
DATA
mail message
(any number of lines)
.
QUIT
e.g.
OutputStream outStream = socket.getOutputStream(); PrintWriter out = new PrintWriter(new OutputStreamWriter(outStream, "utf-8"), true); String hostName = InetAddress.getLocalHost().getHostName(); out.print("HELO " + hostName + "\r\n"); out.print("MAIL FROM: <" + from.getText() + ">\r\n"); out.print("RCPT TO: <" + to.getText() + ">\r\n"); out.print("DATA\r\n"); out.print(("the mail message...\n").replaceAll("\n", "\r\n")); out.print(".\r\n"); out.print("QUIT\r\n"));
3.SMTP规范(RFC 821)规定,每行都要以\r再紧跟一个\n来结尾。
4.有些SMTP服务器并不检查信息的真实性,可以随意填写任何喜欢使用的发件人名字。
5.现在大多数SMTP服务器都会检查守信IP,其他服务器将使用"SMTP之前先POP"规范,即要求在发送任何消息之前先下载你的E-mail,即要求提供密码。
DEMO
import java.awt.EventQueue; import javax.swing.JFrame; public class MailTest { public static void main(String[] args) { EventQueue.invokeLater(new Runnable(){ public void run(){ JFrame frame = new MailTestFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } }); } }
/** * 该程序会因为受限于SMTP服务器检测IP地址的原因,导致失败 */ import java.awt.GridBagLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; import java.util.Scanner; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.SwingWorker; public class MailTestFrame extends JFrame { private Scanner in; private PrintWriter out; private JTextField from; private JTextField to; private JTextField smtpServer; private JTextArea message; private JTextArea comm; public static final int DEFAULT_WIDTH = 300; public static final int DEFAULT_HEIGHT = 300; public MailTestFrame(){ setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); setTitle("MailTest"); setLayout(new GridBagLayout()); add(new JLabel("From:"), new GBC(0,0).setFill(GBC.HORIZONTAL)); from = new JTextField(20); add(from, new GBC(1, 0).setFill(GBC.HORIZONTAL).setWeight(100, 0)); add(new JLabel("TO:"), new GBC(0, 1).setFill(GBC.HORIZONTAL)); to = new JTextField(20); add(to, new GBC(1, 1).setFill(GBC.HORIZONTAL).setWeight(100, 0)); add(new JLabel("SMTP server:"), new GBC(0, 2).setFill(GBC.HORIZONTAL)); smtpServer = new JTextField(20); add(smtpServer, new GBC(1, 2).setFill(GBC.HORIZONTAL).setWeight(100, 0)); message = new JTextArea(); add(new JScrollPane(message), new GBC(0, 3, 2, 1).setFill(GBC.BOTH).setWeight(100, 100)); comm = new JTextArea(); add(new JScrollPane(comm), new GBC(0, 4, 2, 1).setFill(GBC.BOTH).setWeight(100, 100)); JPanel buttonPanel = new JPanel(); add(buttonPanel, new GBC(0, 5, 2, 1)); JButton sendButton = new JButton("Send"); buttonPanel.add(sendButton); sendButton.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent e) { new SwingWorker<Void, Void>(){ protected Void doInBackground() throws Exception{ comm.setText(""); sendMail(); return null; } }.execute(); } }); } public void sendMail(){ try{ // Socket socket = new Socket(smtpServer.getText(), 25); Socket socket = new Socket(); socket.connect(new InetSocketAddress(smtpServer.getText(), 25), 2000); try{ InputStream inStream = socket.getInputStream(); OutputStream outStream = socket.getOutputStream(); in = new Scanner(inStream); out = new PrintWriter(new OutputStreamWriter(outStream, "utf-8"), true); String hostName = InetAddress.getLocalHost().getHostName(); receive(); send("HELO " + hostName); receive(); send("MAIL FROM: <" + from.getText() + ">"); receive(); send("RCPT TO: <" + to.getText() + ">"); receive(); send("DATA"); receive(); send(message.getText()); send("."); receive(); }finally{ socket.close(); } }catch(IOException e){ comm.append("Error: " + e); } } private void send(String str) throws IOException{ comm.append(str); comm.append("\n"); out.print(str.replaceAll("\n", "\r\n")); out.flush(); } private void receive() { String line = in.nextLine(); comm.append(line); comm.append("\n"); } }
import java.awt.GridBagConstraints; import java.awt.Insets; public class GBC extends GridBagConstraints{ public GBC(int gridx, int gridy){ this.gridx = gridx; this.gridy = gridy; } public GBC(int gridx, int gridy, int gridwidth, int gridheight){ this.gridx = gridx; this.gridy = gridy; this.gridwidth = gridwidth; this.gridheight = gridheight; } public GBC setAnchor(int anchor){ this.anchor = anchor; return this; } public GBC setFill(int fill){ this.fill = fill; return this; } public GBC setWeight(double weightx, double weighty){ this.weightx = weightx; this.weighty = weighty; return this; } public GBC setInsets(int distance){ this.insets = new Insets(distance, distance, distance, distance); return this; } public GBC setInsets(int top, int left, int bottom, int right){ this.insets = new Insets(top, left, bottom, right); return this; } public GBC setIpad(int ipadx, int ipady){ this.ipadx = ipadx; this.ipady = ipady; return this; } }