1、电子邮件流程电子邮件流程用户A用户B服务器A服务器B1、用户A通过邮件客户端发送邮件到服务器A2、服务器A将邮件发送到服务器B3、用户B接受服务器B上的邮件用户A邮件发送过程 用户A客户端首先和服务器A建立TCP连接 确认之后,用户A和服务器A之间采用SMTP协议发送邮件内容 邮件内容传输完毕后,发送结束邮件客户端JAVA程序该程序分为4部分,分别为mailclient、envelope、message、smtpconnectionMail cilent为客户端主程序,包括使用界面、按键的定义,整个的发送流程中类的创建message为发送邮件的内容部分,包含有发件人、收件人等内容envelop
2、e为用于smtp协议的信息传递,包含发送接收信息以及message信息smtpconnection为发件过程中和smtp连接的建立以及关闭发送过程中使用的指令HELO 250MAIL FROM 250RCPT TO 250DATA 354QUIT 221Mail Clientimport java.io.*;import .*;import java.awt.*;import java.awt.event.*;public class MailClient extends Frame private Button btSend = new Button(Send);private Button
3、 btClear = new Button(Clear);private Button btQuit = new Button(Quit);private Label serverLabel = new Label(Local mailserver:);private TextField serverField = new TextField(, 40);private Label fromLabel = new Label(From:);private TextField fromField = new TextField(, 40);private Label toLabel = new
4、Label(To:);private TextField toField = new TextField(, 40);private Label subjectLabel = new Label(Subject:);private TextField subjectField = new TextField(, 40);private Label messageLabel = new Label(Message:);private TextArea messageText = new TextArea(10, 40);/* * Create a new MailClient window wi
5、th fields for entering all the relevant * information (From, To, Subject, and message). */public MailClient() super(Java MailClient);Panel serverPanel = new Panel(new BorderLayout();Panel fromPanel = new Panel(new BorderLayout();Panel toPanel = new Panel(new BorderLayout();Panel subjectPanel = new P
6、anel(new BorderLayout();Panel messagePanel = new Panel(new BorderLayout();serverPanel.add(serverLabel, BorderLayout.WEST);serverPanel.add(serverField, BorderLayout.CENTER);fromPanel.add(fromLabel, BorderLayout.WEST);fromPanel.add(fromField, BorderLayout.CENTER);toPanel.add(toLabel, BorderLayout.WEST
7、);toPanel.add(toField, BorderLayout.CENTER);subjectPanel.add(subjectLabel, BorderLayout.WEST);subjectPanel.add(subjectField, BorderLayout.CENTER);messagePanel.add(messageLabel, BorderLayout.NORTH);messagePanel.add(messageText, BorderLayout.CENTER);Panel fieldPanel = new Panel(new GridLayout(0, 1);fi
8、eldPanel.add(serverPanel);fieldPanel.add(fromPanel);fieldPanel.add(toPanel);fieldPanel.add(subjectPanel);/* Create a panel for the buttons and listeners to the buttons. */Panel buttonPanel = new Panel(new GridLayout(1, 0);btSend.addActionListener(new SendListener();btClear.addActionListener(new Clea
9、rListener();btQuit.addActionListener(new QuitListener();buttonPanel.add(btSend);buttonPanel.add(btClear);buttonPanel.add(btQuit);/* Add, pack, and show */add(fieldPanel, BorderLayout.NORTH);add(messagePanel, BorderLayout.CENTER);add(buttonPanel, BorderLayout.SOUTH);pack();show();static public void m
10、ain(String argv) new MailClient();/* Handler for the Send-button. */class SendListener implements ActionListener public void actionPerformed(ActionEvent event) System.out.println(Sending mail);/* Check that we have the local mailserver */if (serverField.getText().equals() System.out.println(Need nam
11、e of local mailserver!);return;/* 确认发送者和接收者的邮件地址正确 */if (fromField.getText().equals() System.out.println(Need sender!);return;if (toField.getText().equals() System.out.println(Need recipient!);return;/* Create the message */Message mailMessage = new Message(fromField.getText(), toField.getText(),sub
12、jectField.getText(),messageText.getText();/* Check that the message is valid, i.e., sender and recipient addresss look ok. */if (!mailMessage.isValid() System.out.println(Mail is not valid!);return;Envelope envelope;try envelope = new Envelope(mailMessage, serverField.getText(); catch (UnknownHostEx
13、ception e) /* If there is an error, do not go further */System.out.println(Unknown host!);return;try SMTPConnection connection = new SMTPConnection(envelope);connection.send(envelope);connection.close(); catch (IOException error) System.out.println(Sending failed: + error);return;System.out.println(
14、Mail send successfully!);/* Clear the fields on the GUI. */class ClearListener implements ActionListener public void actionPerformed(ActionEvent e) System.out.println(Clearing fields);fromField.setText();toField.setText();subjectField.setText();messageText.setText();/* Quit */class QuitListener impl
15、ements ActionListener public void actionPerformed(ActionEvent e) System.exit(0);Messageimport java.util.*;import java.text.*;public class Message public String Headers;public String Body;private String From;private String To;/* To make it look nicer */private static final String CRLF = rn;/* Create
16、the message object by inserting the required headers from RFC 822 (From, To, Date). */public Message(String from, String to, String subject, String text) /* Remove whitespace */From = from.trim();To = to.trim();Headers = From: + From + CRLF;Headers += To: + To + CRLF;Headers += Subject: + subject.tr
17、im() + CRLF;/* A close approximation of the required format. Unfortunately only GMT. */SimpleDateFormat format = new SimpleDateFormat(EEE, dd MMM yyyy HH:mm:ss GMT);String dateString = format.format(new Date();Headers += Date: + dateString + CRLF;Body = text;/* Two functions to access the sender and
18、 recipient. */public String getFrom() return From;public String getTo() return To;/*检查信息的有效性,发送者和接受者的地址 * contains only one -sign. */public boolean isValid() int fromat = From.indexOf();int toat = To.indexOf();if (fromat 1 | (From.length() - fromat) = 1) System.out.println(Sender address is invalid.
19、);return false;if (toat 1 | (To.length() - toat) = 1) System.out.println(Recipient address is invalid.);return false;if (fromat != From.lastIndexOf() System.out.println(Sender address is invalid.);return false;/*检查信息的有效性,发送者和接受者的地址 * contains only one -sign. */public boolean isValid() int fromat = F
20、rom.indexOf();int toat = To.indexOf();if (fromat 1 | (From.length() - fromat) = 1) System.out.println(Sender address is invalid.);return false;if (toat 1 | (To.length() - toat) = 1) System.out.println(Recipient address is invalid.);return false;if (fromat != From.lastIndexOf() System.out.println(Sen
21、der address is invalid.);return false;if (toat != To.lastIndexOf() System.out.println(Recipient address is invalid.);return false;return true;/* For printing the message. */ public String toString() String res;res = Headers + CRLF;res += Body;return res;Envelopeimport java.io.*;import .*;import java
22、.util.*;public class Envelope public String Sender;/* SMTP-recipient, or contents of To-header. */public String Recipient;/* Target MX-host */public String DestHost;public InetAddress DestAddr;/* The actual message. */public Message Message;/* Create the envelope. */public Envelope(Message message,
23、String localServer) throws UnknownHostException /* Get sender and recipient. */Sender = message.getFrom();Recipient = message.getTo();Message = escapeMessage(message);/* Take the name of the local mailserver and map it into an Inet Address */DestHost = localServer;try DestAddr = InetAddress.getByNam
24、e(DestHost); catch (UnknownHostException e) System.out.println(Unknown Host: + DestHost);System.out.println(e);throw e;return;private Message escapeMessage(Message message) String escapeBody = ;String token;StringTokenizer parser = new StringTokenizer(message.Body, n, true);while (parser.hasMoreToke
25、ns() token = parser.nextToken();if (token.startsWith(.) token = . + token;escapeBody += token;message.Body = escapeBody;return message;/* For printing the envelope. Only for debug. */public String toString() String res = Sender: + Sender + n;res += Recipient: + Recipient +n;res += MX-host: + DestHos
26、t + , address: + DestAddr + n;res += Message: + n;res += Message.toString();return res;SMTPConnectionimport .*;import java.io.*;import java.util.*;public class SMTPConnection private Socket connection;/* Streams for reading and writing the socket */private BufferedReader fromServer;private DataOutpu
27、tStream toServer;private static final int SMTP_PORT = 25;private static final String CRLF = rn;/* Are we connected? Used in close() to determine what to do. */private boolean isConnected = false;/* Create an SMTPConnection object. Create the socket and the associated streams. Initialize * SMTP conne
28、ction. */public SMTPConnection(Envelope envelope) throws IOException connection = new Socket(envelope.DestAddr, SMTP_PORT);fromServer = new BufferedReader(new InputStreamReader(connection.getInputStream();toServer = new DataOutputStream(connection.getOutputStream();/* Read a line from server and che
29、ck that the reply code is 220. If not, throw an IOException. */String reply = fromServer.readLine();if (reply.startsWith(220) else throw new IOException(Server reply + reply);/* SMTP handshake. We need the name of the local machine. * Send the appropriate SMTP handshake command. */String localhost =
30、 envelope.DestHost;try sendCommand(HELO + localhost, 250); catch (IOException error) System.out.println(error);System.exit(1); catch (Exception e) System.out.println(e);System.exit(1);isConnected = true;/* Send the message. Write the correct SMTP-commands in the correct order. No checking for errors
31、, * just throw them to the caller. */public void send(Envelope envelope) throws IOException /* Send all the necessary commands to send a message. Call sendCommand() to do the dirty * work. Do _not_ catch the exception thrown from sendCommand(). */sendCommand(MAIL FROM: + envelope.Sender + CRLF, 250)
32、;sendCommand(RCPT TO: + envelope.Recipient + CRLF, 250);sendCommand(DATA + CRLF + envelope.Message.Headers + envelope.Message.Body + CRLF + . + CRLF, 354);/* Close the connection. First, terminate on SMTP level, then close the socket. */public void close() isConnected = false;try /*sendCommand(QUIT,
33、 221);*/sendCommand(QUIT, 250);connection.close(); catch (IOException e) System.out.println(Unable to close connection: + e);isConnected = true;/* Send an SMTP command to the server. Check that the reply code is what is is supposed to be * according to RFC 821. */private void sendCommand(String comm
34、and, int rc) throws IOException String reply;toServer.writeBytes(command);toServer.writeBytes(CRLF);System.out.println(Me: + command + n);reply = fromServer.readLine();System.out.println(Server: + reply + n);if(!reply.startsWith(String.valueOf(rc) throw new IOException(Server reply: + reply);/*if(rc
35、 != parseReply(reply) throw new IOException(Server reply + reply);*/*if (command.equalsIgnoreCase(HELO) & rc != 250) | (command.equalsIgnoreCase(MAIL FROM) & rc != 250) | (command.equalsIgnoreCase(RCPT TO) & rc != 250)| (command.equalsIgnoreCase(DATA) & rc != 354)| (command.equalsIgnoreCase(QUIT) &
36、rc != 221) throw new IOException(Server replys + rc);*/* Parse the reply line from the server. Returns the reply code. */private int parseReply(String reply) return Integer.parseInt(reply);/* Destructor. Closes the connection if something bad happens. */protected void finalize() throws Throwable if
37、(isConnected) close();super.finalize();Eclipse程序运行过程程序运行过程ESMTPESMTP,英文全称是“Extended SMTP”,顾名思义,扩展SMTP就是对标准SMTP协议进行的扩展本地本地SMTP服务器的搭建服务器的搭建采用一个smtp服务器软件,可以搭建本地smtp服务器,完成发件过程SSLSSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议。TLS与SSL在传输层对网络连接进行加密。SSL协议提供的服务主要有: 1)认证用户和服务器,确保数据发送到正确的客户机和服务器; 2)加密数据以防止数据中途被窃取; 3)维护数据的完整性,确保数据在传输过程中不被改变。 HttpsnHTTPS(Secure Hypertext Transfer Protocol)安全超文本传输协议 nhttps是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,https的安全基础是SSL