java网络学习之 MailToURLConnection 源码解析(9)

先写一个小例子,用来展示如何使用MailToURLConnection 来发送邮件

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.URL;
import java.net.URLConnection;

/**
 * This program sends e-mail using a mailto: URL
 */
public class SendMail {
  public static void main(String[] args) {
    try {
      // If the user specified a mailhost, tell the system about it.
      if (args.length >= 1)
        System.getProperties().put("mail.host", args[0]);

      // A Reader stream to read from the console
      BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

      // Ask the user for the from, to, and subject lines
      System.out.print("From: ");
      String from = in.readLine();
      System.out.print("To: ");
      String to = in.readLine();
      System.out.print("Subject: ");
      String subject = in.readLine();

      // Establish a network connection for sending mail
      URL u = new URL("mailto:" + to); // Create a mailto: URL
      URLConnection c = u.openConnection(); // Create its URLConnection
      c.setDoInput(false); // Specify no input from it
      c.setDoOutput(true); // Specify we'll do output
      System.out.println("Connecting..."); // Tell the user
      System.out.flush(); // Tell them right now
      c.connect(); // Connect to mail host
      PrintWriter out = // Get output stream to host
      new PrintWriter(new OutputStreamWriter(c.getOutputStream()));

      // We're talking to the SMTP server now.
      // Write out mail headers. Don't let users fake the From address
      out.print("From: \"" + from + "\" <" + System.getProperty("user.name") + "@"
          + InetAddress.getLocalHost().getHostName() + ">\r\n");
      out.print("To: " + to + "\r\n");
      out.print("Subject: " + subject + "\r\n");
      out.print("\r\n"); // blank line to end the list of headers

      // Now ask the user to enter the body of the message
      System.out.println("Enter the message. " + "End with a '.' on a line by itself.");
      // Read message line by line and send it out.
      String line;
      for (;;) {
        line = in.readLine();
        if ((line == null) || line.equals("."))
          break;
        out.print(line + "\r\n");
      }

      // Close (and flush) the stream to terminate the message
      out.close();
      // Tell the user it was successfully sent.
      System.out.println("Message sent.");
    } catch (Exception e) { // Handle any exceptions, print error message.
      System.err.println(e);
      System.err.println("Usage: java SendMail [<mailhost>]");
    }
  }
}

    

openConncetion方法就是构造了一个MailToURLConnection对象。

 

接下来我们看看其中的原理:sun.net.www.protocol.mailto.MailToURLConnection的实现

其中connect 方法源码如下(可以看到这个方法就是初始化了 一个SmtpClient 对象)

public void connect() throws IOException {
    this.client = new SmtpClient(this.connectTimeout);
    this.client.setReadTimeout(this.readTimeout);
}
SmtpClient构造函数如下:  mailhost是邮件服务器地址,可以看到会从系统属性中读取mail.host,如果不存在默认为localhost,
然后就开始连接服务器。

public SmtpClient(int var1) throws IOException {
    this.setConnectTimeout(var1);

    try {
        this.mailhost = (String)AccessController.doPrivileged(new GetPropertyAction("mail.host"));
        if (this.mailhost != null) {
            this.openServer(this.mailhost);
            return;
        }
    } catch (Exception var4) {
        ;
    }

    try {
        this.mailhost = "localhost";
        this.openServer(this.mailhost);
    } catch (Exception var3) {
        this.mailhost = "mailhost";
        this.openServer(this.mailhost);
    }

}

其中openServer 的源码如下:这段代码的意思 就是 先创建一个连接,这里默认邮件服务器端口号是25,然后发送一个helo命令 

private void openServer(String var1) throws IOException {
    this.mailhost = var1;
    this.openServer(this.mailhost, 25);
    this.issueCommand("helo " + InetAddress.getLocalHost().getHostName() + "\r\n", 250);
}

其中 openServer 的方法源码: .可以看到这里创建了一个客户端socket

public void openServer(String var1, int var2) throws IOException, UnknownHostException {
    if (this.serverSocket != null) {
        this.closeServer();
    }

    this.serverSocket = this.doConnect(var1, var2);

    try {
        this.serverOutput = new PrintStream(new BufferedOutputStream(this.serverSocket.getOutputStream()), true, encoding);
    } catch (UnsupportedEncodingException var4) {
        throw new InternalError(encoding + "encoding not found", var4);
    }

    this.serverInput = new BufferedInputStream(this.serverSocket.getInputStream());
}
doConnect 源码如下:
protected Socket doConnect(String var1, int var2) throws IOException, UnknownHostException {
    Socket var3;
    if (this.proxy != null) {
        if (this.proxy.type() == Type.SOCKS) {
            var3 = (Socket)AccessController.doPrivileged(new PrivilegedAction<Socket>() {
                public Socket run() {
                    return new Socket(NetworkClient.this.proxy);
                }
            });
        } else if (this.proxy.type() == Type.DIRECT) {
            var3 = this.createSocket();
        } else {
            var3 = new Socket(Proxy.NO_PROXY);
        }
    } else {
        var3 = this.createSocket();
    }

    if (this.connectTimeout >= 0) {
        var3.connect(new InetSocketAddress(var1, var2), this.connectTimeout);
    } else if (defaultConnectTimeout > 0) {
        var3.connect(new InetSocketAddress(var1, var2), defaultConnectTimeout);
    } else {
        var3.connect(new InetSocketAddress(var1, var2));
    }

    if (this.readTimeout >= 0) {
        var3.setSoTimeout(this.readTimeout);
    } else if (defaultSoTimeout > 0) {
        var3.setSoTimeout(defaultSoTimeout);
    }

    return var3;
}

 

getOutputStream源码如下:
public synchronized OutputStream getOutputStream() throws IOException {
    if (this.os != null) {
        return this.os;
    } else if (this.is != null) {
        throw new IOException("Cannot write output after reading input.");
    } else {
        this.connect();
        String var1 = ParseUtil.decode(this.url.getPath());
        this.client.from(this.getFromAddress());
        this.client.to(var1);
        this.os = this.client.startMessage();
        return this.os;
    }
}
public PrintStream startMessage() throws IOException {
    this.issueCommand("data\r\n", 354);

    try {
        this.message = new SmtpPrintStream(this.serverOutput, this);
    } catch (UnsupportedEncodingException var2) {
        throw new InternalError(encoding + " encoding not found", var2);
    }

    return this.message;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值