找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 5402|回复: 1

【Java】java轻量级电子邮件类smtpmail(不是JavaMail),支持附件

[复制链接]
发表于 2015-12-31 06:31:19 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×
用法:
1、初始化。
  1. smtpmail sm=new smtpmail();
  2. sm.SetServer(服务器地址,端口号,用户名,密码,发件人,收件人);
复制代码
2、发送简单的纯文本邮件:
  1. sm.SendTextMail(是否使用SSL加密,如果不使用SSL加密是不是服务器必须支持TLS加密才继续发送,标题,内容);
复制代码
3、发送复杂的邮件:
  1. try
  2. {
  3.         sm.StartSendMail(是否使用SSL加密,如果不使用SSL加密是不是服务器必须支持TLS加密才继续发送,标题,有没有附件);
  4.         sm.SendPlainText(纯文本内容);
  5.         sm.SendHTML(HTML格式的内容);
  6.         sm.SendAttachment(附件的MIME类型,附件名,文件名,附件内容字节数组);
  7.         sm.FinishSendMail();
  8. }
  9. catch(IOException e)
  10. {
  11.         e.printStackTrace();
  12. }
复制代码
4、调试:
  1. int 最后收到的状态码 = sm.GetLastStatus();
  2. String 最后发送的内容 = sm.GetLastSend();
  3. String 最后收到的内容 = sm.GetLastRecv();
  4. String 最后发送的内容和最后收到的内容 = sm.GetLastSendRecv();
复制代码
5、杂项
  • 使用SSL加密的时候,你需要在smtpmail类的文件夹下村一个SMTP服务器的数字签名文件。否则握手失败——抛出HandShakeException。
    举个例子,我要使用QQ的smtp服务器,获取它数字签名的方法是用浏览器进入https://mail.qq.com然后在浏览器的“锁”标识找到证书,并将其复制到文件。
    smtps.png
    IE.png viewsign.png
    然后在弹出的窗口里找到“详细信息”选项卡,点开,点“复制到文件”按钮。
    20151231072219.png
    然后跟着向导走一遍就行了。向导的话详细的自己看着办吧。
  • 不使用SSL加密或者STARTTLS加密的电子邮箱服务器基本上已经不存在了。
  • 这个类只需要实体化一遍就可以随便使用。只需要在发送前保证SetServer填的那些内容都对就行了。


源码:
  1. import java.io.BufferedReader;
  2. import java.io.IOException;
  3. import java.io.InputStreamReader;
  4. import java.io.PrintStream;
  5. import java.net.Socket;
  6. import java.util.UUID;
  7. import java.util.Base64;

  8. import javax.net.ssl.SSLSocket;
  9. import javax.net.ssl.SSLSocketFactory;
  10. /**
  11. * Created by 0xAA55 on 2015/12/7.
  12. * Author: 0xAA55
  13. * Website: http://www.0xaa55.com
  14. */

  15. public class smtpmail
  16. {
  17.         final private String nl="\r\n";//换行符
  18.         final private String nlnl=nl+nl;//换行符
  19.         private String m_Sep;//分隔符
  20.         //服务器
  21.         private String m_ServerAddr;
  22.         private int m_ServerPort;
  23.         //用户账号
  24.         private String m_Username;
  25.         private String m_Password;
  26.         //发送者和接收者
  27.         private String m_MailFrom;
  28.         private String m_RcptTo;
  29.         //状态
  30.         private String m_LastSend;
  31.         private String m_LastRecv;
  32.         private int m_LastStatus;
  33.         //读写器
  34.         private Socket m_s;
  35.         private BufferedReader m_br;
  36.         private PrintStream m_ps;

  37.         //=========================================================================
  38.         //方法:ConnectToServer
  39.         //描述:连接到服务器
  40.         private void ConnectToServer()throws IOException
  41.         {
  42.                 m_s=new Socket(m_ServerAddr,m_ServerPort);
  43.                 m_br=new BufferedReader(new InputStreamReader(m_s.getInputStream()));
  44.                 m_ps=new PrintStream(m_s.getOutputStream());
  45.         }

  46.         //=========================================================================
  47.         //方法:SSLConnectToServer
  48.         //描述:使用SSL加密连接到服务器
  49.         private void SSLConnectToServer()throws IOException
  50.         {
  51.                 SSLSocket ss=(SSLSocket)((SSLSocketFactory)SSLSocketFactory.getDefault())
  52.                                 .createSocket(m_ServerAddr,m_ServerPort);
  53.                 ss.setEnableSessionCreation(true);
  54.                 ss.setUseClientMode(true);
  55.                 ss.startHandshake();
  56.                 m_s=ss;
  57.                 m_br=new BufferedReader(new InputStreamReader(ss.getInputStream()));
  58.                 m_ps=new PrintStream(ss.getOutputStream());
  59.         }

  60.         //=========================================================================
  61.         //方法:TurnToSSL
  62.         //描述:转为SSL安全连接
  63.         private void TurnToSSL()throws IOException
  64.         {
  65.                 SSLSocket ss=(SSLSocket)((SSLSocketFactory)SSLSocketFactory.getDefault())
  66.                                 .createSocket(m_s,m_ServerAddr,m_ServerPort,true);
  67.                 ss.setEnableSessionCreation(true);
  68.                 ss.setUseClientMode(true);
  69.                 //STARTTLS没有握手
  70.                 //ss.startHandshake();
  71.                 m_s=ss;
  72.                 m_br=new BufferedReader(new InputStreamReader(ss.getInputStream()));
  73.                 m_ps=new PrintStream(ss.getOutputStream());
  74.         }

  75.         //=========================================================================
  76.         //方法:SendSMTPData
  77.         //描述:发送SMTP数据
  78.         private void SendSMTPData(String command)throws IOException
  79.         {
  80.                 m_ps.print(command);
  81.                 m_LastSend=command;
  82.                 // Log.d("smtpmail","Send:"+m_LastSend.replace(nl,""));
  83.                 System.out.println("Send:"+m_LastSend);
  84.         }

  85.         //=========================================================================
  86.         //方法:RecvSMTPData
  87.         //描述:获取一条服务器返回的内容,取得状态码
  88.         private int RecvSMTPData()throws IOException
  89.         {
  90.                 //从服务器读取一行返回的内容
  91.                 m_LastRecv=m_br.readLine();
  92.                 // Log.d("smtpmail","Recv:"+m_LastRecv);
  93.                 System.out.println("Recv:"+m_LastRecv);

  94.                 if(m_LastRecv == null || m_LastRecv.length() == 0)//如果没有取得内容,则抛出错误
  95.                         throw new IOException("RecvSMTPData: no status code.");

  96.                 //分析字符串,从前面取得状态码
  97.                 char[]ch=m_LastRecv.toCharArray();
  98.                 int i;
  99.                 m_LastStatus=0;
  100.                 for(i=0;i<m_LastRecv.length();i++)
  101.                 {
  102.                         //读取数字直到遇到别的字符
  103.                         if(ch[i]>='0'&&ch[i]<='9')
  104.                                 m_LastStatus=m_LastStatus*10+ch[i]-'0';
  105.                         else
  106.                                 break;
  107.                 }
  108.                 if(i==0)//如果没有取得内容,则抛出错误
  109.                         throw new IOException("RecvSMTPData: no status code.");
  110.                 return m_LastStatus;
  111.         }

  112.         //=========================================================================
  113.         //方法:StartTls
  114.         //描述:发送STARTTLS,然后获取服务器的支持情况
  115.         private boolean StartTls()throws IOException
  116.         {
  117.                 //发送STARTTLS
  118.                 SendSMTPData("STARTTLS"+nl);

  119.                 //接收到220时表示STARTTLS成功,而接收到的值超过300的就表示失败
  120.                 do
  121.                 {
  122.                         if(RecvSMTPData()==220)
  123.                                 return true;
  124.                 }while(m_LastStatus<300);
  125.                 return false;
  126.         }

  127.         //=========================================================================
  128.         //方法:AuthLogin
  129.         //描述:验证用户名和密码
  130.         private boolean AuthLogin()throws IOException
  131.         {
  132.                 //发送AUTH LOGIN,然后接收服务器返回
  133.                 SendSMTPData("AUTH LOGIN "+nl);

  134.                 //略过所有的2xx返回内容
  135.                 do
  136.                         RecvSMTPData();
  137.                 while(m_LastStatus<300);

  138.                 //得到3xx状态后,发送账号密码
  139.                 if(m_LastStatus<400)
  140.                 {
  141.                         //一次性完成账号和密码的发送
  142.                         SendSMTPData(Base64.getEncoder().encodeToString(m_Username.getBytes())+nl+
  143.                                                  Base64.getEncoder().encodeToString(m_Password.getBytes())+nl);
  144.                 }
  145.                 else
  146.                         return false;//服务器并没有要求输入用户名和密码(或者,530,必须先STARTTLS)

  147.                 //发送完账号和密码,等服务器返回结果
  148.                 for(;;)
  149.                 {
  150.                         RecvSMTPData();//接收内容
  151.                         if(m_LastStatus<300)return true;//验证成功
  152.                         if(m_LastStatus>=400)return false;//其它情况
  153.                 }
  154.         }

  155.         //=========================================================================
  156.         //方法:SetFromTo
  157.         //描述:设置发件人和收件人。要求之前服务器返回的数据都已完成读取
  158.         private boolean SetFromTo()throws IOException
  159.         {
  160.                 SendSMTPData("MAIL FROM:<"+m_MailFrom+">"+nl);
  161.                 //250 OK
  162.                 //501 mail from address must be same as authorization user
  163.                 if(RecvSMTPData()>=300)return false;

  164.                 SendSMTPData("RCPT TO:<"+m_RcptTo+">"+nl);
  165.                 //250 OK
  166.                 //550 Mailbox not found or access denied
  167.                 if(RecvSMTPData()>=300)return false;
  168.                 return true;
  169.         }

  170.         //=========================================================================
  171.         //方法:Quit
  172.         //描述:告知服务器关闭连接,同时自己也关闭连接
  173.         private void Quit()
  174.         {
  175.                 try
  176.                 {
  177.                         SendSMTPData("QUIT"+nl);
  178.                         m_s.close();
  179.                 }catch(IOException e)
  180.                 {
  181.                         e.printStackTrace();
  182.                 }
  183.         }

  184.         //=========================================================================
  185.         //公开方法

  186.         //=========================================================================
  187.         //方法:构造
  188.         //描述:初始化类
  189.         public smtpmail()
  190.         {
  191.                 m_LastSend="";
  192.                 m_LastRecv="";
  193.                 m_LastStatus=0;
  194.         }

  195.         //=========================================================================
  196.         //方法:SetServer
  197.         //描述:设置服务器
  198.         void SetServer(String addr,int port,String user,String pswd,String from,String rcpt)
  199.         {
  200.                 m_ServerAddr=addr;
  201.                 m_ServerPort=port;
  202.                 m_Username=user;
  203.                 m_Password=pswd;
  204.                 m_MailFrom=from;
  205.                 m_RcptTo=rcpt;
  206.         }

  207.         //=========================================================================
  208.         //方法:StartSendMail
  209.         //描述:开始发送邮件
  210.         boolean StartSendMail(boolean SSL,boolean MustUseTls,String Subject,boolean HaveAttachment)throws IOException
  211.         {
  212.                 boolean UseTls=false;

  213.                 if(SSL)
  214.                         SSLConnectToServer();
  215.                 else
  216.                         ConnectToServer();

  217.                 //Hello
  218.                 SendSMTPData("EHLO "+m_ServerAddr+nl);
  219.                 if(RecvSMTPData()!=220)
  220.                 {
  221.                         Quit();
  222.                         return false;
  223.                 }
  224.                 if(!SSL)//如果不是SSL加密,就尝试进行STARTTLS握手
  225.                 {
  226.                         if(StartTls())
  227.                         {
  228.                                 UseTls=true;//成功表示支持使用TLS加密
  229.                                 TurnToSSL();
  230.                                 SendSMTPData("EHLO "+m_ServerAddr+nl);
  231.                         }
  232.                         else
  233.                         {
  234.                                 if(m_LastStatus == 454)//服务器不支持STARTTLS
  235.                                 {
  236.                                         if(MustUseTls)
  237.                                         {
  238.                                                 Quit();
  239.                                                 return false;//而用户却需要使用STARTTLS
  240.                                         }
  241.                                 }
  242.                                 else//StartTls返回的其它信息,视为错误
  243.                                 {
  244.                                         Quit();
  245.                                         return false;
  246.                                 }
  247.                         }
  248.                 }

  249.                 //验证用户名和密码
  250.                 //这之前服务器可能会发回很多的我们不需要的内容,通过这个可以把它刷掉
  251.                 if(!AuthLogin())
  252.                 {
  253.                         Quit();
  254.                         return false;
  255.                 }

  256.                 //设置发件人和收件人
  257.                 if(!SetFromTo())
  258.                 {
  259.                         Quit();
  260.                         return false;
  261.                 }

  262.                 SendSMTPData("DATA"+nl);
  263.                 //354 Enter mail, end with "." on a line by itself
  264.                 do
  265.                 {
  266.                         if(RecvSMTPData()>=400) return false;
  267.                 }
  268.                 while(m_LastStatus<300);

  269.                 m_Sep="_Part_"+UUID.randomUUID().toString();

  270.                 SendSMTPData("From:<"+m_MailFrom+">"+nl+
  271.                                          "To:<"+m_RcptTo+">"+nl+
  272.                                          "Subject: =?UTF-8?B?"+
  273.                                          Base64.getEncoder().encodeToString(Subject.getBytes("UTF-8"))+"?="+nl+
  274.                                          "MIME-Version: 1.0"+nl+
  275.                                          "Content-Type: multipart/"+(HaveAttachment?"mixed;":"alternative;")+" boundary=""+m_Sep+"""+nlnl);

  276.                 return true;
  277.         }

  278.         //=========================================================================
  279.         //方法:SendPlainText
  280.         //描述:发送纯文本
  281.         void SendPlainText(String Text)throws IOException
  282.         {
  283.                 SendSMTPData("--"+m_Sep+nl+
  284.                                          "Content-Type:text/plain; charset=utf-8"+nl+
  285.                                          "Content-transfer-encoding: Base64"+nl+nl+
  286.                                          Base64.getEncoder().encodeToString(Text.getBytes("UTF-8"))+nlnl);
  287.         }

  288.         //=========================================================================
  289.         //方法:SendHTML
  290.         //描述:发送HTML格式的内容
  291.         void SendHTML(String TextHTML)throws IOException
  292.         {
  293.                 SendSMTPData("--"+m_Sep+nl+
  294.                                          "Content-Type:text/html; charset=utf-8"+nl+
  295.                                          "Content-transfer-encoding: Base64"+nl+nl+
  296.                                          Base64.getEncoder().encodeToString(TextHTML.getBytes("UTF-8"))+nlnl);
  297.         }

  298.         //=========================================================================
  299.         //方法:SendAttachment
  300.         //描述:发送附件
  301.         void SendAttachment(String MIMEType,String name,String filename,byte[] data)throws IOException
  302.         {
  303.                 SendSMTPData("--"+m_Sep+nl+
  304.                                          "Content-Type: "+MIMEType+"; name="=?UTF-8?B?"+
  305.                                          Base64.getEncoder().encodeToString(name.getBytes("UTF-8"))+"?=""+nl+
  306.                                          "Content-Transfer-Encoding: Base64"+nl+
  307.                                          "Content-Disposition: attachment; filename="=?UTF-8?B?"+
  308.                                          Base64.getEncoder().encodeToString(filename.getBytes("UTF-8"))+"?=""+nl+nl+
  309.                                          Base64.getEncoder().encodeToString(data)+nlnl);
  310.         }

  311.         //=========================================================================
  312.         //方法:FinishSendMail
  313.         //描述:结束邮件的发送
  314.         boolean FinishSendMail()throws IOException
  315.         {
  316.                 SendSMTPData("--"+m_Sep+"--"+nl+"."+nl);

  317.                 //250 2.0.0 tB8BJfTa093352 Message accepted for delivery
  318.                 if(RecvSMTPData()>=300)
  319.                 {
  320.                         Quit();
  321.                         return false;
  322.                 }
  323.                 Quit();
  324.                 return true;
  325.         }

  326.         //=========================================================================
  327.         //方法:SendTextMail
  328.         //描述:发送纯文本邮件
  329.         boolean SendTextMail(boolean usessl,boolean MustUseTls,String Subject,String Content)
  330.         {
  331.                 try
  332.                 {
  333.                         if(!StartSendMail(usessl,true,Subject,false))
  334.                                 return false;
  335.                         SendPlainText(Content);
  336.                         return FinishSendMail();
  337.                 }
  338.                 catch(IOException e)
  339.                 {
  340.                         e.printStackTrace();
  341.                         return false;
  342.                 }
  343.         }

  344.         //=========================================================================
  345.         //方法:Get
  346.         int GetLastStatus()
  347.         {
  348.                 return m_LastStatus;
  349.         }
  350.         String GetLastSend()
  351.         {
  352.                 return m_LastSend;
  353.         }
  354.         String GetLastRecv()
  355.         {
  356.                 return m_LastRecv;
  357.         }
  358.         String GetLastSendRecv()
  359.         {
  360.                 return "Last send:"+m_LastSend+"\nLast recv:"+m_LastRecv;
  361.         }
  362. }
复制代码
SRC & BIN: smtpmail.7z (7.32 KB, 下载次数: 2, 售价: 10 个宅币)

相关链接:
http://www.0xaa55.com/thread-1650-1-1.html
回复

使用道具 举报

发表于 2020-12-4 10:27:51 | 显示全部楼层
感谢分享。。。
回复

使用道具 举报

本版积分规则

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-11-21 22:37 , Processed in 0.038897 second(s), 30 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表