基于TClientSocket简单模拟需要验证的SMTP邮件发送附件(C++Builder)

来源:互联网 发布:新浪微博数据统计 编辑:程序博客网 时间:2024/05/17 07:21
  1. //---------------------------------------------------------------------------
  2. #include <vcl.h>
  3. #pragma hdrstop
  4. #include <dos.h>
  5. #include "Mail.h"
  6. //---------------------------------------------------------------------------
  7. #pragma package(smart_init)
  8. #pragma resource "*.dfm"
  9. TForm1 *Form1;
  10. //---------------------------------------------------------------------------
  11. __fastcall TForm1::TForm1(TComponent* Owner)
  12.         : TForm(Owner)
  13. {
  14. }
  15. //---------------------------------------------------------------------------
  16. //#define BUFFER_SIZE   0x0348 /*  840 Max Stack Size 64kb*/
  17. #define BUFFER_SIZE 0x1DE5 /* 7653                    */
  18. #define BUFFER_SIZE_3   BUFFER_SIZE*(57+0)
  19. #define BUFFER_SIZE_4   BUFFER_SIZE*(76+2)
  20. AnsiString EncodeBase64Char(char Value[],int Len)
  21. {
  22.    char Buffer[BUFFER_SIZE_4+1];
  23.    char Base64Table[64]={'A','B','C','D','E','F','G','H',
  24.                          'I','J','K','L','M','N','O','P',
  25.                          'Q','R','S','T','U','V','W','X',
  26.                          'Y','Z','a','b','c','d','e','f',
  27.                          'g','h','i','j','k','l','m','n',
  28.                          'o','p','q','r','s','t','u','v',
  29.                          'w','x','y','z','0','1','2','3',
  30.                          '4','5','6','7','8','9','+','/'
  31.                         };
  32.    for(int i=0;i<Len;i+=3)
  33.    {
  34.       //____________________________________________________
  35.       //  ↓☆☆☆☆↓                                   
  36.       //00111111111111111111111111
  37.       //  ├→ 1  ←┤├→ 2  ←┤├→ 3  ←┤
  38.       //  876543218765432187654321
  39.       //00111111
  40.       //----------------------------------------------------
  41.       Buffer[i/57*2+i/3+i+0]=Base64Table[(Value[i]>>2)&0x003f];
  42.       //____________________________________________________
  43.       //        ↓☆☆☆☆↓                                   
  44.       //00111111111111111111111111
  45.       //  ├→ 1  ←┤├→ 2  ←┤├→ 3  ←┤
  46.       //  876543218765432187654321
  47.       //      00111111
  48.       //----------------------------------------------------
  49.       Buffer[i/57*2+i/3+i+1]=Base64Table[((Value[i]&0x0003)<<4)|
  50.                                          ((Value[i+1]>>4)&0x000f)];
  51.       //____________________________________________________
  52.       //              ↓☆☆☆☆↓                                   
  53.       //00111111111111111111111111
  54.       //  ├→ 1  ←┤├→ 2  ←┤├→ 3  ←┤
  55.       //  876543218765432187654321
  56.       //            00111111
  57.       //----------------------------------------------------
  58.       Buffer[i/57*2+i/3+i+2]=Base64Table[(((Value[i+1]&0x000f)<<2))|
  59.                                           ((Value[i+2]>>6)&0x0003)];
  60.       //____________________________________________________
  61.       //                    ↓☆☆☆☆↓                                   
  62.       //00111111111111111111111111
  63.       //  ├→ 1  ←┤├→ 2  ←┤├→ 3  ←┤
  64.       //  876543218765432187654321
  65.       //                  00111111
  66.       //----------------------------------------------------
  67.       Buffer[i/57*2+i/3+i+3]=Base64Table[Value[i+2]&0x003f];
  68.       Buffer[i/57*2+i/3+i+4]='/0';
  69.       if((i+3)%57==0)
  70.       {
  71.          Buffer[i/57*2+i/3+i+4]='/r';
  72.          Buffer[i/57*2+i/3+i+5]='/n';
  73.       }
  74.    }
  75.    Buffer[BUFFER_SIZE_4]='/0';
  76.    return AnsiString(Buffer);
  77. }
  78. void EncodeBase64File(AnsiString FileName,TStream *DestStream)
  79. {
  80.    __int64 i;
  81.    int sLen;
  82.    int ssLen;
  83.    AnsiString DestString;
  84.    char Buffer[BUFFER_SIZE_3];
  85.    TFileStream *SourceStream;
  86.    SourceStream=new TFileStream(FileName,fmOpenRead|fmShareDenyWrite);
  87.    try
  88.    {
  89.       for(i=0;i<SourceStream->Size;i+=BUFFER_SIZE_3)
  90.       {
  91.          ssLen=SourceStream->Size-i;
  92.          if(ssLen>BUFFER_SIZE_3)
  93.             ssLen=BUFFER_SIZE_3;
  94.          SourceStream->ReadBuffer(&Buffer,ssLen);
  95.          sLen=ssLen;
  96.          switch(ssLen%3)
  97.          {
  98.             case 2:
  99.                   Buffer[ssLen+1]='/0';
  100.                   sLen+=1;
  101.             case 1:
  102.                   Buffer[ssLen+0]='/0';
  103.                   sLen+=1;
  104.          }
  105.          DestString=EncodeBase64Char(Buffer,sLen);
  106.          sLen=DestString.Length();
  107.          DestStream->Seek(0,soFromEnd);
  108.          DestStream->WriteBuffer(DestString.c_str(),sLen);
  109.          ssLen=4;
  110.          if(DestString.c_str()[sLen]=='/n')
  111.             ssLen+=2;
  112.       }
  113.       switch(SourceStream->Size%3)
  114.       {
  115.          case 1:
  116.                DestString="==";
  117.                DestStream->Seek(2-ssLen,soFromEnd);
  118.                DestStream->WriteBuffer(DestString.c_str(),DestString.Length());
  119.                break;
  120.          case 2:
  121.                DestString="=";
  122.                DestStream->Seek(3-ssLen,soFromEnd);
  123.                DestStream->WriteBuffer(DestString.c_str(),DestString.Length());
  124.       }
  125.    }
  126.    __finally
  127.    {
  128.       SourceStream->Free();
  129.    }
  130. }
  131. AnsiString Base64EnTable(int so)
  132. {
  133.    if(so>=0&&so<=25)
  134.       return AnsiString((char)(so+65));
  135.    if(so>=26&&so<=51)
  136.       return AnsiString((char)(so+71));
  137.    if(so>=52&&so<=61)
  138.       return AnsiString((char)(so-4));
  139.    if(so==62)
  140.       return "+";
  141.    return "/";
  142. }
  143. AnsiString EncodeBase64(AnsiString source)
  144. {
  145.    AnsiString dest="",addtail="";
  146.    if(source.Length()==0)
  147.       return "";
  148.    for(int j=0;j<source.Length();j+=3)
  149.    {
  150.       int k,k1,l,l1,m,m1,n,mn;
  151.       k=source.c_str()[j];
  152.       j+1>source.Length()?l=0:l=source.c_str()[j+1];
  153.       j+2>source.Length()?m=0:m=source.c_str()[j+2];
  154.       k&=0xFF;  //read a unsigned char
  155.       l&=0xFF;
  156.       m&=0xFF;
  157.       mn=k<<16; //make three characters to a 4-bit number
  158.       mn+=l<<8;
  159.       mn+=m;
  160.       k1=mn>>18;//the first character's index in base64table
  161.       k1&=0x3F;
  162.       l1=mn>>12;//the second
  163.       l1&=0x3F;
  164.       m1=mn>>6; //the third
  165.       m1&=0x3F;
  166.       n=mn&0x3F;//the fourth
  167.       dest+=Base64EnTable(k1)+Base64EnTable(l1)+
  168.         Base64EnTable(m1)+Base64EnTable(n);
  169.       if((j+3)%57==0)
  170.          dest+="/r/n";
  171.    }
  172.    switch(source.Length()%3)
  173.    {
  174.       case 1:
  175.              dest=dest.SubString(1,dest.Length()-2);
  176.              dest+="==";
  177.              break;
  178.       case 2:
  179.              dest=dest.SubString(1,dest.Length()-1);
  180.              dest+="=";
  181.              break;
  182.    }
  183.    return dest;
  184. }
  185. void __fastcall TForm1::AddClick(TObject *Sender)
  186. {
  187. if(OpenDialog1->Execute())
  188. {
  189. Attach->Items->AddStrings(OpenDialog1->Files);
  190. }
  191. }
  192. //---------------------------------------------------------------------------
  193. void __fastcall TForm1::AttachClick(TObject *Sender)
  194. {
  195. if(Attach->SelCount>0)
  196.    Del->Enabled=true;
  197. else
  198.    Del->Enabled=false;
  199. }
  200. //---------------------------------------------------------------------------
  201. void __fastcall TForm1::DelClick(TObject *Sender)
  202. {
  203. Attach->DeleteSelected();
  204. }
  205. //---------------------------------------------------------------------------
  206. void __fastcall TForm1::ClientSocket1Read(TObject *Sender,
  207.       TCustomWinSocket *Socket)
  208. {
  209. AnsiString t=Socket->ReceiveText();
  210. AnsiString SendMsg;
  211. Mess->Lines->Add(t.SubString(1,t.Length()-2));
  212. switch(ppp)
  213. {
  214. case 0:
  215.         ppp++;
  216.         SendMsg="EHLO "+SMTPSERVER->Text.Trim()+"/r/n";
  217.         if(!AUTH->Checked)
  218.         {
  219.            ppp+=3;
  220.            SendMsg="HELO "+SMTPSERVER->Text.Trim()+"/r/n";
  221.         }
  222.         Mess->Lines->Add(SendMsg.SubString(1,SendMsg.Length()-2));
  223.         Socket->SendText(SendMsg);
  224.         break;
  225. case 1:
  226.         ppp++;
  227.         SendMsg="AUTH LOGIN/r/n";
  228.         Mess->Lines->Add(SendMsg.SubString(1,SendMsg.Length()-2));
  229.         Socket->SendText(SendMsg);
  230.         break;
  231. case 2:
  232.         ppp++;
  233.         SendMsg=EncodeBase64(USERID->Text)+"/r/n";
  234.         Mess->Lines->Add(SendMsg.SubString(1,SendMsg.Length()-2));
  235.         Socket->SendText(SendMsg);
  236.         break;
  237. case 3:
  238.         ppp++;
  239.         SendMsg=EncodeBase64(PWD->Text)+"/r/n";
  240.         Mess->Lines->Add(SendMsg.SubString(1,SendMsg.Length()-2));
  241.         Socket->SendText(SendMsg);
  242.         break;
  243. case 4:
  244.         ppp++;
  245.         SendMsg="MAIL FROM: <"+FROM->Text.Trim()+">/r/n";
  246.         Mess->Lines->Add(SendMsg.SubString(1,SendMsg.Length()-2));
  247.         Socket->SendText(SendMsg);
  248.         break;
  249. case 5:
  250.         {ppp++;
  251.         SendMsg="RCPT TO: <"+TO->Text.Trim()+">/r/n";
  252.         if(TOCC->Text.Trim().Length()>0)
  253.            SendMsg+="RCPT TO: <"+TOCC->Text.Trim()+">/r/n";
  254.         Mess->Lines->Add(SendMsg.SubString(1,SendMsg.Length()-2));
  255.         Socket->SendText(SendMsg);
  256.         }
  257.         break;
  258. case 3+3:
  259.         ppp++;
  260.         SendMsg="DATA/r/n";
  261.         Mess->Lines->Add(SendMsg.SubString(1,SendMsg.Length()-2));
  262.         Socket->SendText(SendMsg);
  263.         break;
  264. case 4+3:
  265.         {
  266.         TMemoryStream *memstr;
  267.         ppp++;
  268.         Mess->Lines->Add("Sending Data ...");
  269.         memstr=new TMemoryStream();
  270.         try
  271.         {
  272.         AnsiString sendtext=AnsiString("Message-ID: <000e01c26603$6f0e7a30$0a00a8c0@yj01>")+
  273.         "/r/nFrom: /""+Edit1->Text.Trim()+"/" <"+FROM->Text.Trim()+">/r/n"+
  274.         "To: <"+TO->Text.Trim()+">/r/n";
  275.         if(TOCC->Text.Trim()!="")
  276.            sendtext+=AnsiString("Cc: <"+TOCC->Text.Trim()+">/r/n");
  277.         SYSTEMTIME t;
  278.         GetLocalTime(&t);
  279.         AnsiString tday[7]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"},
  280.         tmon[12]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
  281.         if(SUBJECT->Text.Trim().Length()>0)
  282.         sendtext+="Subject: =?gb2312?B?"+EncodeBase64(SUBJECT->Text.Trim())+"?=/r/n";
  283.         else
  284.            sendtext+="Subject:/r/n";
  285.         sendtext+="Date: "+tday[t.wDayOfWeek]+Now().FormatString(", dd ")+tmon[t.wMonth-1]+Now().FormatString(" yyyy hh:mm:ss +0800")+"/r/n"+
  286.         "MIME-Version: 1.0/r/n"
  287.         "Content-Type: multipart/mixed;/r/n"
  288.         "   boundary=/"----=_NextPart_000_000A_01C26646.7D0E7AC0/"/r/n"+
  289.         "X-Priority: 3/r/n"+
  290.         "X-MSMail-Priority: Normal/r/n"+
  291.         "X-Mailer: Morncolorsoft E_Mail Sender 1.00.0000.0000/r/n"+
  292.         "X-Mime: Morncolorsoft Mailer Inside V1.00.0000.0000/r/n/r/n"+
  293.         "This is a multi-part message in MIME format./r/n/r/n"+
  294.         "------=_NextPart_000_000A_01C26646.7D0E7AC0/r/n"+
  295.         "Content-Type: multipart/alternative;/r/n"+
  296.         "   boundary=/"----=_NextPart_001_000B_01C26646.7D0E7AC0/"/r/n/r/n/r/n"+
  297.         "------=_NextPart_001_000B_01C26646.7D0E7AC0/r/n"+
  298.         "Content-Type: text/plain;/r/n"+
  299.         "   charset=/"gb2312/"/r/n"+
  300.         "Content-Transfer-Encoding: base64/r/n/r/n"+
  301.         EncodeBase64(Body->Text)+"/r/n/r/n"+
  302.         "------=_NextPart_001_000B_01C26646.7D0E7AC0/r/n"+
  303.         "Content-Type: text/html;/r/n"+
  304.         "   charset=/"gb2312/"/r/n"+
  305.         "Content-Transfer-Encoding: base64/r/n/r/n"+
  306.         EncodeBase64(AnsiString("<!DOCTYPE HTML PUBLIC /"-//W3C//DTD HTML 4.0 Transitional//EN/">/r/n")+
  307.         "<HTML><HEAD>/r/n"+
  308.         "<META http-equiv=Content-Type content=/"text/html; charset=gb2312/">/r/n"+
  309.         "<META content=/"MSHTML 6.00.2600.0/" name=GENERATOR>/r/n"+
  310.         "<STYLE></STYLE>/r/n"+
  311.         "</HEAD>/r/n"+
  312.         "<BODY bgColor=#ffffff>/r/n"+
  313.         "<DIV><FONT size=2><PRE>"+Body->Text+"</PRE></FONT></DIV></BODY></HTML>")+
  314.         "/r/n------=_NextPart_001_000B_01C26646.7D0E7AC0--/r/n";
  315.         if(Attach->Count>0)
  316.         {
  317.            memstr->WriteBuffer(sendtext.c_str(),sendtext.Length());
  318.            for(int kk=0;kk<Attach->Count;kk++)
  319.               if(FileExists(Attach->Items->Strings[kk]))
  320.               {
  321.                  AnsiString sendtextt=AnsiString("/r/n------=_NextPart_000_000A_01C26646.7D0E7AC0/r/n")+
  322.                  "Content-Type: application/octet-stream;/r/n"+
  323.                  "  name=/""+ExtractFileName(Attach->Items->Strings[kk])+"/"/r/n"+
  324.                  "Content-Transfer-Encoding: base64/r/n"+
  325.                  "Content-Disposition: attachment;/r/n"+
  326.                  "  filename=/""+ExtractFileName(Attach->Items->Strings[kk])+"/"/r/n/r/n";
  327.                  memstr->Seek(0,soFromEnd);
  328.                  memstr->WriteBuffer(sendtextt.c_str(),sendtextt.Length());
  329.                  EncodeBase64File(Attach->Items->Strings[kk],memstr);
  330.                  memstr->Seek(0,soFromEnd);
  331.                  AnsiString ttt="/r/n";
  332.                  memstr->WriteBuffer(ttt.c_str(),ttt.Length());
  333.               }
  334.            AnsiString sendtexttt="/r/n------=_NextPart_000_000A_01C26646.7D0E7AC0--/r/n/r/n./r/n";
  335.            memstr->Seek(0,soFromEnd);
  336.            memstr->WriteBuffer(sendtexttt.c_str(),sendtexttt.Length());
  337.            memstr->Seek(0,soFromBeginning);
  338.            //Mess->Lines->LoadFromStream(memstr);
  339.            Socket->SendStream(memstr);
  340.         }
  341.         else
  342.         Socket->SendText(sendtext+"/r/n./r/n");
  343.         }
  344.         catch(...)
  345.         {
  346.         memstr->Free();
  347.         }
  348.         break;
  349.         }
  350. case 5+3:
  351.         ppp++;
  352.         SendMsg="QUIT/r/n";
  353.         Mess->Lines->Add(SendMsg.SubString(1,SendMsg.Length()-2));
  354.         Socket->SendText(SendMsg);
  355.         break;
  356. case 6+3:
  357.         ppp=-1;
  358.         break;
  359. }
  360. }
  361. //---------------------------------------------------------------------------
  362. void __fastcall TForm1::SendClick(TObject *Sender)
  363. {
  364. if(SMTPSERVER->Text.Trim()=="")
  365.    return;
  366. if(PORT->Text.Trim()=="")
  367.    return;
  368. if(TO->Text.Trim()=="")
  369.    return;
  370. int port=StrToInt(PORT->Text.Trim());
  371. if(port==0)
  372.    port=25;
  373. Send->Enabled=false;
  374. ppp=0;
  375. ClientSocket1->Host=SMTPSERVER->Text.Trim();
  376. ClientSocket1->Port=port;
  377. ClientSocket1->Open();
  378. }
  379. //---------------------------------------------------------------------------
  380. void __fastcall TForm1::ClientSocket1Disconnect(TObject *Sender,
  381.       TCustomWinSocket *Socket)
  382. {
  383. Send->Enabled=true;
  384. }
  385. //---------------------------------------------------------------------------
  386. void __fastcall TForm1::GetClick(TObject *Sender)
  387. {
  388. /*        TTime t;
  389.         TDate d;
  390.         t=Now();
  391.         d=Now();
  392.         ShowMessage(t.DayOfWeek());
  393. //"Date: Wed, 25 Sep 2002 08:17:50 +0800/r/n"+
  394.         ShowMessage( d.FormatString("DDD, dd MMM yyyy hh:mm:ss +0800"));
  395. */
  396. AnsiString ss="";
  397. for(int i=0;i<Body->Text.Length();i++)
  398. {
  399. ss+=IntToStr((int)Body->Text.c_str()[i])+" ";
  400. }
  401. Mess->Text=ss;
  402. }
  403. //---------------------------------------------------------------------------
  404. void __fastcall TForm1::ClientSocket1Error(TObject *Sender,
  405.       TCustomWinSocket *Socket, TErrorEvent ErrorEvent, int &ErrorCode)
  406. {
  407.  Send->Enabled=true;
  408.  ErrorCode=0;
  409.  Socket->Close();
  410. }
  411. //---------------------------------------------------------------------------
原创粉丝点击