根据RFC821SMTP协议写的发Email方法

★★★ 转载自: http://stephen830.iteye.com/blog/255099 

这是老早以前根据RFC821协议[SIMPLE MAIL TRANSFER PROTOCOL]写的用于发email的方法。附件部分有点问题。有兴趣的朋友可以参考下。 

关于RFC821协议[SIMPLE MAIL TRANSFER PROTOCOL]的具体内容可以访问: http://james.apache.org/server/rfclist/smtp/rfc0821.txt 

下面是MailTool.java的具体内容: 

Java代码  收藏代码
  1. /* 
  2.  * Created on 2005-6-1 
  3.  * Author stephen 
  4.  * Email zhoujianqiang AT gmail DOT com 
  5.  * CopyRight(C)2005-2008 , All rights reserved. 
  6.  */  
  7. package com.soft4j.utility;  
  8.   
  9. import java.io.File;  
  10. import java.io.FileInputStream;  
  11. import java.io.FileNotFoundException;  
  12. import java.io.IOException;  
  13. import java.io.InputStream;  
  14. import java.io.OutputStream;  
  15. import java.net.Socket;  
  16.   
  17. /** 
  18.  * 电子邮件Email的处理类. 
  19.  *  
  20.  * @author stephen 
  21.  * @version 1.0.0 
  22.  */  
  23. public final class MailTool {  
  24.   
  25.     private final static String END_FLAG = "\r\n";//SMTP/ESMTP命令结束标记  
  26.     private final static String EMAIL_ATTACH_SIGN = "=====att";//邮件附件的表示符号  
  27.   
  28.     private String smtpServer = null;//邮件发送服务器域名  
  29.     private int smtpPort = 25;//邮件发送端口  
  30.     private Socket clientMailSocket;//邮件连接socket  
  31.     private InputStream inData;//接收数据      
  32.     private OutputStream outData;//发送数据  
  33.     private String mailUserName = null;//邮件账户  
  34.     private String mailUserPass = null;//邮件账户的密码  
  35.     private String mailTo = null;//邮件发送目标  
  36.     private String mailFrom = null;//邮件发送人  
  37.     private String mailSubject = null;//邮件主题  
  38.     private String mailBody = null;//邮件正文     
  39.     private String mailShowTo = null;//邮件内容抬头部分-邮件发送目标  
  40.     private String mailShowFrom = null;//邮件内容抬头部分-邮件发送人  
  41.     private String[] mailAttachFile = null;//邮件附件对应的本地文件名(包含绝对路径)  
  42.     private int mailType = 1;//邮件类型:1=文本邮件,2=HTML邮件  
  43.       
  44.     /** 
  45.      * @return Returns the mailAttachFile. 
  46.      */  
  47.     public String[] getMailAttachFile() {  
  48.         return mailAttachFile;  
  49.     }  
  50.     /** 
  51.      * @param mailAttachFile The mailAttachFile to set. 
  52.      */  
  53.     public void setMailAttachFile(String[] mailAttachFile) {  
  54.         this.mailAttachFile = mailAttachFile;  
  55.     }  
  56.     /** 
  57.      * @return Returns the mailShowFrom. 
  58.      */  
  59.     public String getMailShowFrom() {  
  60.         return mailShowFrom;  
  61.     }  
  62.     /** 
  63.      * @param mailShowFrom The mailShowFrom to set. 
  64.      */  
  65.     public void setMailShowFrom(String mailShowFrom) {  
  66.         this.mailShowFrom = mailShowFrom;  
  67.     }  
  68.     /** 
  69.      * @return Returns the mailShowTo. 
  70.      */  
  71.     public String getMailShowTo() {  
  72.         return mailShowTo;  
  73.     }  
  74.     /** 
  75.      * @param mailShowTo The mailShowTo to set. 
  76.      */  
  77.     public void setMailShowTo(String mailShowTo) {  
  78.         this.mailShowTo = mailShowTo;  
  79.     }  
  80.   
  81.       
  82.     /** 
  83.      * @return Returns the mailBody. 
  84.      */  
  85.     public String getMailBody() {  
  86.         return mailBody;  
  87.     }  
  88.     /** 
  89.      * @param mailBody The mailBody to set. 
  90.      */  
  91.     public void setMailBody(String mailBody) {  
  92.         this.mailBody = mailBody;  
  93.     }  
  94.     /** 
  95.      * @return Returns the mailFrom. 
  96.      */  
  97.     public String getMailFrom() {  
  98.         return mailFrom;  
  99.     }  
  100.     /** 
  101.      * @param mailFrom The mailFrom to set. 
  102.      */  
  103.     public void setMailFrom(String mailFrom) {  
  104.         this.mailFrom = mailFrom;  
  105.     }  
  106.     /** 
  107.      * @return Returns the mailSubject. 
  108.      */  
  109.     public String getMailSubject() {  
  110.         return mailSubject;  
  111.     }  
  112.     /** 
  113.      * @param mailSubject The mailSubject to set. 
  114.      */  
  115.     public void setMailSubject(String mailSubject) {  
  116.         this.mailSubject = mailSubject;  
  117.     }  
  118.     /** 
  119.      * @return Returns the mailTo. 
  120.      */  
  121.     public String getMailTo() {  
  122.         return mailTo;  
  123.     }  
  124.     /** 
  125.      * @param mailTo The mailTo to set. 
  126.      */  
  127.     public void setMailTo(String mailTo) {  
  128.         this.mailTo = mailTo;  
  129.     }  
  130.     /** 
  131.      * @return Returns the mailUserName. 
  132.      */  
  133.     public String getMailUserName() {  
  134.         return mailUserName;  
  135.     }  
  136.     /** 
  137.      * @param mailUserName The mailUserName to set. 
  138.      */  
  139.     public void setMailUserName(String mailUserName) {  
  140.         this.mailUserName = mailUserName;  
  141.     }  
  142.     /** 
  143.      * @return Returns the mailUserPass. 
  144.      */  
  145.     public String getMailUserPass() {  
  146.         return mailUserPass;  
  147.     }  
  148.     /** 
  149.      * @param mailUserPass The mailUserPass to set. 
  150.      */  
  151.     public void setMailUserPass(String mailUserPass) {  
  152.         this.mailUserPass = mailUserPass;  
  153.     }  
  154.       
  155.       
  156.   
  157.     /** 
  158.      * 获取属性- 
  159.      * @return Returns the mailType. 
  160.      */  
  161.     public int getMailType() {  
  162.         return mailType;  
  163.     }  
  164.     /** 
  165.      * 设置属性- 
  166.      * @param mailType The mailType to set. 
  167.      */  
  168.     public void setMailType(int mailType) {  
  169.         this.mailType = mailType;  
  170.     }  
  171.     /** 
  172.      * 构造器方法. 
  173.      * @param _smtpServer smtp服务器名(ip地址) 
  174.      * @param _smtpPort smtp端口号. 
  175.      */  
  176.     public MailTool(String smtpServer,int smtpPort){  
  177.         this.smtpServer = smtpServer;  
  178.         this.smtpPort = smtpPort;  
  179.     }  
  180.       
  181.       
  182.     /** 
  183.      * 与smtp邮件服务器建立连结. 
  184.      * @return 
  185.      */  
  186.     public boolean createConnection(){  
  187.         try {  
  188.             freeAll();  
  189.             clientMailSocket = new Socket(smtpServer, smtpPort);  
  190.             inData = clientMailSocket.getInputStream();  
  191.             outData = clientMailSocket.getOutputStream();  
  192.             fetchCMDResult();//当首次连接服务器后有返回值,必须取走该返回值,否则后面命令的返回值无法判断  
  193.         } catch (IOException e) {  
  194.             System.out.println("Can't create the connection with " + smtpServer + "on port " + smtpPort + ".", Log.STD_ERR);  
  195.             return false;  
  196.         }  
  197.         return true;  
  198.     }  
  199.       
  200.     /** 
  201.      *  
  202.      * @param in 
  203.      * @return 
  204.      */  
  205.     public static String response(InputStream in){  
  206.         byte[] buffer = new byte[1024];  
  207.         StringBuffer inData = new StringBuffer();  
  208.         int n = 0;  
  209.         try {  
  210.                 n = in.read(buffer);  
  211.                 inData.append(new String(buffer, 0, n));  
  212.               
  213.         } catch (IOException e) {  
  214.             e.printStackTrace();  
  215.         }  
  216.         return inData.toString();  
  217.   
  218.     }  
  219.       
  220.     public static void send(String s, OutputStream out){  
  221.         byte[] buffer = s.getBytes();  
  222.         try {  
  223.             out.write(buffer);  
  224.             out.flush();  
  225.         } catch (IOException e) {  
  226.             e.printStackTrace();  
  227.         }  
  228.     }  
  229.   
  230.   
  231.     public String fetchCMDResult(){  
  232.         return response(inData);  
  233.     }  
  234.       
  235.     public boolean sendCmd(String _cmd) {  
  236.         if (_cmd != null) {  
  237.             send(_cmd,outData);  
  238.         }  
  239.         return true;  
  240.     }  
  241.       
  242.     /** 
  243.      * 发送邮件 
  244.      * 服务器为ESMTP时候采用本方法 
  245.      * @return true=send ok,false=send failed. 
  246.      */  
  247.     public boolean sendMail() {  
  248.           
  249.         //打开与邮件服务器的连接  
  250.         if(!createConnection()){  
  251.             return false;  
  252.         }  
  253.         StringBuffer theContent = new StringBuffer();  
  254.   
  255.         //EHLO  
  256.         theContent.append("EHLO ");  
  257.         theContent.append(smtpServer);  
  258.         theContent.append(END_FLAG);  
  259.         sendCmd(theContent.toString());  
  260.         if(fetchCMDResult().indexOf("250")==-1return false;  
  261.         //AUTH LOGIN  
  262.         theContent.delete(0,theContent.length());  
  263.         theContent.append("AUTH LOGIN");  
  264.         theContent.append(END_FLAG);  
  265.         sendCmd(theContent.toString());  
  266.         try { Thread.sleep(5000); } catch (Exception e) {}  
  267.         if(fetchCMDResult().indexOf("334")==-1return false;  
  268.         //用户名  
  269.         theContent.delete(0,theContent.length());  
  270.         theContent.append(Base64Encode(this.mailUserName));  
  271.         theContent.append(END_FLAG);  
  272.         sendCmd(theContent.toString());  
  273.         if(fetchCMDResult().indexOf("334")==-1return false;  
  274.         //密码  
  275.         theContent.delete(0,theContent.length());  
  276.         theContent.append(Base64Encode(this.mailUserPass));  
  277.         theContent.append(END_FLAG);  
  278.         sendCmd(theContent.toString());  
  279.         try { Thread.sleep(5000); } catch (Exception e) {}  
  280.         if(fetchCMDResult().indexOf("235")==-1return false;  
  281.         //邮件发送者  
  282.         theContent.delete(0,theContent.length());  
  283.         theContent.append("MAIL FROM:");  
  284.         theContent.append("<");  
  285.         theContent.append(this.mailFrom);  
  286.         theContent.append(">");  
  287.         theContent.append(END_FLAG);  
  288.         sendCmd(theContent.toString());  
  289.         if(fetchCMDResult().indexOf("250")==-1return false;  
  290.         //邮件发送目标地址  
  291.         theContent.delete(0,theContent.length());  
  292.         theContent.append("RCPT TO:");  
  293.         theContent.append("<");  
  294.         theContent.append(this.mailTo);  
  295.         theContent.append(">");  
  296.         theContent.append(END_FLAG);  
  297.         sendCmd(theContent.toString());  
  298.         if(fetchCMDResult().indexOf("250")==-1return false;  
  299.           
  300.         //邮件内容-开始  
  301.         theContent.delete(0,theContent.length());  
  302.         theContent.append("DATA");  
  303.         theContent.append(END_FLAG);  
  304.         sendCmd(theContent.toString());  
  305.         if(fetchCMDResult().indexOf("354")==-1return false;  
  306.         //邮件内容-邮件抬头部分  
  307.         theContent.delete(0,theContent.length());  
  308.         theContent.append("From:");  
  309.         theContent.append(this.mailShowFrom);  
  310.         theContent.append(END_FLAG);  
  311.         theContent.append("To:");  
  312.         theContent.append(this.mailShowTo);  
  313.         theContent.append(END_FLAG);  
  314.         theContent.append("Subject:");  
  315.         theContent.append(this.mailSubject);  
  316.         theContent.append(END_FLAG);  
  317.         theContent.append("Mime-Version: 1.0");  
  318.         theContent.append(END_FLAG);  
  319.           
  320.   
  321.         theContent.append("Content-Type: multipart/mixed;Boundary=\"");//设置附件表示符  
  322.         theContent.append(EMAIL_ATTACH_SIGN);  
  323.         theContent.append("\"");  
  324.         theContent.append(END_FLAG);//在正文内容前必须有2个END_FLAG标记  
  325.         theContent.append(END_FLAG);  
  326.         sendCmd(theContent.toString());  
  327.   
  328.         //邮件内容-正文部分  
  329.         theContent.delete(0,theContent.length());  
  330.         theContent.append("--");  
  331.         theContent.append(EMAIL_ATTACH_SIGN);  
  332.         theContent.append(END_FLAG);  
  333.         switch(mailType){  
  334.             case 2:theContent.append("Content-type:text/html;");break;  
  335.             default:theContent.append("Content-type:text/plain;");break;  
  336.         }  
  337.         theContent.append(END_FLAG);  
  338.         theContent.append("Content-Transfer-Encoding: base64");  
  339.         theContent.append(END_FLAG);  
  340.         theContent.append(END_FLAG);  
  341.         theContent.append(Base64Encode(this.mailBody));  
  342.         theContent.append(END_FLAG);  
  343.         theContent.append(END_FLAG);  
  344.         sendCmd(theContent.toString());  
  345.           
  346.         //邮件内容-附件部分  
  347.         mailAttachFile = null;  
  348.         if(mailAttachFile!=null && mailAttachFile.length>0){  
  349.             for(int i=0;i<this.mailAttachFile.length;i++){  
  350.                 //发送附件抬头  
  351.                 theContent.delete(0,theContent.length());  
  352.                 theContent.append("--");  
  353.                 theContent.append(EMAIL_ATTACH_SIGN);  
  354.                 theContent.append(i);  
  355.                 theContent.append(END_FLAG);  
  356.                 theContent.append("Content-Type:image/gif;name=\"aaa.gif\"");  
  357.                 theContent.append(END_FLAG);  
  358.                 theContent.append("Content-Transfer-Encoding:base64");  
  359.                 theContent.append(END_FLAG);  
  360.                 theContent.append("Content-Disposition:attachment;name=\"aaa.gif\"");  
  361.                 theContent.append(END_FLAG);  
  362.                 theContent.append(END_FLAG);  
  363.                 sendCmd(theContent.toString());  
  364.                   
  365.                 //发送附件内容  
  366.                 sendBase64Data(new StringBuffer(Base64Encode(readFile(mailAttachFile[i]))));  
  367.                   
  368.                 //发送附件结束  
  369.                 /* 
  370.                 theContent = new StringBuffer(); 
  371.                 theContent.append(END_FLAG); 
  372.                 theContent.append("--"); 
  373.                 theContent.append(EMAIL_ATTACH_SIGN); 
  374.                 theContent.append(i); 
  375.                 theContent.append("--"); 
  376.                 theContent.append(END_FLAG); 
  377.                 sendCmd(theContent.toString()); 
  378.                 */  
  379.             }  
  380.               
  381.         }  
  382.           
  383.           
  384.         //发送附件结束  
  385.         theContent.delete(0,theContent.length());  
  386.         theContent.append(END_FLAG);  
  387.         theContent.append(END_FLAG);  
  388.         theContent.append("--");  
  389.         theContent.append(EMAIL_ATTACH_SIGN);  
  390.         theContent.append("--");  
  391.         theContent.append(END_FLAG);  
  392.         sendCmd(theContent.toString());  
  393.           
  394.         //邮件内容-结束标记  
  395.         theContent.delete(0,theContent.length());  
  396.         theContent.append(END_FLAG);  
  397.         theContent.append(".");  
  398.         theContent.append(END_FLAG);  
  399.         sendCmd(theContent.toString());  
  400.         if(fetchCMDResult().indexOf("250")==-1return false;  
  401.           
  402.         //退出断开服务器连接  
  403.         theContent.delete(0,theContent.length());  
  404.         theContent.append("QUIT");  
  405.         theContent.append(END_FLAG);  
  406.         sendCmd(theContent.toString());  
  407.         fetchCMDResult();  
  408.           
  409.         //邮件发送成功后释放资源  
  410.         freeAll();  
  411.         theContent = null;  
  412.           
  413.         return true;//邮件发送成功  
  414.     }  
  415.       
  416.     /** 
  417.      * 发送经过Base64编码后的数据 
  418.      * @param src 
  419.      */  
  420.     public void sendBase64Data(StringBuffer srcData){  
  421.         int LEN_CMD_DATA = 76;  
  422.         int startIndex = 0;  
  423.         int totalLength = 0;  
  424.         if(srcData!=null && srcData.length()>0){  
  425.             totalLength = srcData.length();  
  426.             while(true){  
  427.                 if(startIndex+LEN_CMD_DATA<totalLength){  
  428.                     sendCmd(srcData.substring(startIndex,startIndex+LEN_CMD_DATA));  
  429.                     sendCmd(END_FLAG);  
  430.                 }else{  
  431.                     sendCmd(srcData.substring(startIndex,totalLength));  
  432.                     sendCmd(END_FLAG);  
  433.                     break;  
  434.                 }  
  435.                 startIndex = startIndex+LEN_CMD_DATA;  
  436.             }  
  437.         }  
  438.     }  
  439.       
  440.     /** 
  441.      * 释放所有资源 
  442.      * 
  443.      */  
  444.     public void freeAll(){  
  445.         if(inData!=null){  
  446.             try {  
  447.                 inData.close();  
  448.             } catch (IOException e) {  
  449.                 e.printStackTrace();  
  450.             }  
  451.             inData = null;  
  452.         }  
  453.           
  454.         if(outData!=null){  
  455.             try {  
  456.                 outData.close();  
  457.             } catch (IOException e) {  
  458.                 e.printStackTrace();  
  459.             }  
  460.             outData = null;  
  461.         }     
  462.           
  463.         if(clientMailSocket!=null){  
  464.             try {  
  465.                 clientMailSocket.close();  
  466.             } catch (IOException e) {  
  467.                 e.printStackTrace();  
  468.             }  
  469.             clientMailSocket = null;  
  470.         }  
  471.           
  472.     }  
  473.       
  474.       
  475.     /** 
  476.      * 读取文件内容 
  477.      * @param fileName 
  478.      * @return 
  479.      */  
  480.     public String readFile(String fileName){  
  481.         byte[] fileBuffer = new byte[1024];  
  482.         int realSize = 0;  
  483.         StringBuffer readContent = new StringBuffer();  
  484.         try {  
  485.             InputStream inFile = new FileInputStream(new File(fileName));  
  486.             while(true){  
  487.                 realSize = inFile.read(fileBuffer);  
  488.                 if(-1==realSize) break;  
  489.                 readContent.append(new String(fileBuffer,0,realSize));  
  490.             }  
  491.         } catch (FileNotFoundException e) {  
  492.             e.printStackTrace();  
  493.         } catch (IOException e) {  
  494.             e.printStackTrace();  
  495.         }  
  496.         return readContent.toString();  
  497.     }  
  498.   
  499.     /** 
  500.      * Base64编码函数 
  501.      * 将指定的字符串编码为Base64格式的字符串 
  502.      * @param src 
  503.      * @return 
  504.      */  
  505.     public static String Base64Encode(String src) {  
  506.         if (src == null || src.length() == 0)  
  507.             return "";  
  508.         String EncodingTable = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";  
  509.         byte[] Buffer = src.getBytes();  
  510.         int ReadNow, i, res;  
  511.         char[] WriteBuf = new char[4];  
  512.         char[] Buf = new char[3];  
  513.         String EncodedStr = "";  
  514.         int ReadIndex = 0;  
  515.         int Len = Buffer.length;  
  516.         boolean isEnd;  
  517.         int BytesWritten = 0;  
  518.         ReadNow = 0;  
  519.         do {  
  520.             isEnd = false;  
  521.             for (i = 0; i < 3; i++) {  
  522.                 if (ReadIndex >= Len) {  
  523.                     isEnd = true;  
  524.                     ReadNow = i;  
  525.                     break;  
  526.                 }  
  527.                 Buf[i] = (char) (((byte) Buffer[ReadIndex]) & 0x00FF);  
  528.                 ReadIndex = ReadIndex + 1;  
  529.             }  
  530.             if (isEnd)  
  531.                 break;  
  532.             WriteBuf[0] = EncodingTable.charAt((Buf[0] >> 2) & 0x003F);  
  533.             WriteBuf[1] = EncodingTable  
  534.                     .charAt(((Buf[0] & 3) << 4 | (Buf[1] >> 4)) & 0x003F);  
  535.             WriteBuf[2] = EncodingTable  
  536.                     .charAt(((Buf[1] & 15) << 2 | (Buf[2] >> 6)) & 0x003F);  
  537.             WriteBuf[3] = EncodingTable.charAt((Buf[2] & 63) & 0x003F);  
  538.             for (i = 0; i < 4; i++)  
  539.                 EncodedStr = EncodedStr + WriteBuf[i];  
  540.             BytesWritten = BytesWritten + 4;  
  541.             if ((BytesWritten % 76) == 0) {  
  542.                 EncodedStr = EncodedStr + "";  
  543.             }  
  544.         } while (ReadNow != 3);  
  545.         if (ReadNow < 3) {  
  546.             switch (ReadNow) {  
  547.             case 1:  
  548.                 WriteBuf[0] = EncodingTable.charAt((Buf[0] >> 2) & 0x003F);  
  549.                 WriteBuf[1] = EncodingTable  
  550.                         .charAt(((Buf[0] & 3) << 4) & 0x003F);  
  551.                 WriteBuf[2] = '=';  
  552.                 WriteBuf[3] = '=';  
  553.                 for (i = 0; i < 4; i++)  
  554.                     EncodedStr = EncodedStr + WriteBuf[i];  
  555.                 break;  
  556.             case 2:  
  557.                 WriteBuf[0] = EncodingTable.charAt((Buf[0] >> 2) & 0x003F);  
  558.                 WriteBuf[1] = EncodingTable  
  559.                         .charAt(((Buf[0] & 3) << 4 | (Buf[1] >> 4)) & 0x003F);  
  560.                 WriteBuf[2] = EncodingTable  
  561.                         .charAt(((Buf[1] & 15) << 2) & 0x003F);  
  562.                 WriteBuf[3] = '=';  
  563.                 for (i = 0; i < 4; i++)  
  564.                     EncodedStr = EncodedStr + WriteBuf[i];  
  565.                 break;  
  566.             default:  
  567.                 break;  
  568.             }  
  569.         }  
  570.         return (EncodedStr);  
  571.     }  
  572.       
  573.     /** 
  574.      * 测试用的main方法. 
  575.      * @param args main方法的参数. 
  576.      */  
  577.     public static void main(String[] args) {  
  578.           
  579.         MailTool foxMail = new MailTool("mail.xxx.com",25);//smtp服务器地址  
  580.         foxMail.setMailUserName("username@xxx.com");//mail.xxx.com的一个email用户  
  581.         foxMail.setMailUserPass("password");//username@xxx.com账户的密码  
  582.         foxMail.setMailTo("username@yyy.com");//发送目标email地址  
  583.         foxMail.setMailFrom("username@xxx.com");  
  584.         foxMail.setMailShowTo("你好");  
  585.         foxMail.setMailShowFrom("哈哈");  
  586.         foxMail.setMailSubject("hello用中文主题");  
  587.         foxMail.setMailBody("welcome for you. 中文呀.aaa \r\n再来一行");  
  588.   
  589.         if(foxMail.sendMail()){  
  590.             System.out.println("OK.");  
  591.         }else{  
  592.             System.out.println("False.");  
  593.         }  
  594.         foxMail = null;  
  595.           
  596.     }  
  597. }  



当初写这个方法,主要是为了学习下RFC821协议,比较简单,没有作很深入的研究. 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值