C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 Q&A
C++Builder Programming Q&A
[37533] Re:Re:[SMTP] SMTP 서버 없이 전송되게 하는 코드나 컴포넌트가 있을까요?
초보자 [] 1330 읽음    2004-10-07 23:44
임문환.실업자 님이 쓰신 글 :
: 초보자 님이 쓰신 글 :
: : SMTP 서버 없이 이메일 전송할수 있는 예제코드나, 컴포넌트 없을까요?
: : 델마당이나 여기저기 기웃거리고, 나름대로 SMTP 쪽 공부한다고 하는데....
: : 머리가 나쁜지 영 이해를 하지 못하겠네요.
: :
: : 없다면, 구현을 하기위한 대략적인 OUTLINE이라도 그려주실분 없나요?
: : 그럼 즐거운 하루 되시길 바랍니다.
:
: 이 것을 어디에 사용하려 하시는지 궁금해지네요.
: 컴포넌트로 되어 있는 것은 모르겠구요 간단히 흐름만을 말씀드리겠습니다.
:
: SMTP(Simple Mail Transfer Protocol) Sender 구현에 관해
:
: 관련 RFC: rfc821(http://www.ietf.org/rfc/rfc0821.txt?number=821)
:
: 0. 아래 작업은 보통 별도의 스레드 내에서 하는 것이 좋음
:   애플리케이션 내의 공용 자원들에 대해서는 동기화 메커니즘을 사용하는 게 안전함.
:
: 1. SMTP Receiver에 접속
:  - SMTP 기본 포트는 25이지만 이를 무시하는 경우도 있으므로 각 서버마다 실제 포트를 알아야 함
:  - 호스트와 포트를 알았다고 해도 등록된 IP들에만 개방하는 경우가 있어 접속 불가능할 수도 있음
:  - TCP blocking 모드를 사용

: 2. 일단 접속에 성공하면 Receiver 쪽에서 응답코드를 반환하게 됨.
:  즉, 아래와 같은 형식의 문자열을 반환함.
:  220 USC-ISIF.ARPA Simple Mail Transfer Service Ready\r\n
:  Sender는 이를 받아서 코드가 220인지 확인해야 하고 220이 아니면 메일을 보낼 수 없음.

: 3. Sender는 "HELO"를 아래와 같은 형식으로 Receiver에게 보내야 함.
:    HELO HostNameOfSender\r\n
:    예: HELO LBL-UNIX.ARPA\r\n
:    Receiver는 이를 받고 확인차원에서 아래 메시지를 보냄
:    250 HostNameOfReceiver\r\n
:    예: 250 USC-ISIF.ARPA\r\n
:    응답코드가 250이 아니면 메일을 보낼 수 없음.
:   
: 4. 아래 메시지를 Receiver에 보냄
:    MAIL FROM:<mo@LBL-UNIX.ARPA>\r\n
:    위에서 <> 안에 보내는이의 메일주소를 넣으면 됨.
:    Receiver가 메일을 처리할 의사가 있으면 아래와 같은 형식으로 250 응답코드를 보내게 됨.
:    250 OK\r\n
:    응답코드가 250이 아니면 메일을 처리할 의사가 없는 것임.
:    응답코드는 여러가지 중 하나인데 각 응답코드에 대해서는 rfc821 문서를 참고.
:
: 5. 아래와 같은 형식으로 받는이의 메일주소를 Receiver에게 보냄
:   RCPT TO:<fred@USC-ISIF.ARPA>\r\n
:   Receiver가 250 또는 251이 아닌 응답코드를 보내면 메일을 보낼 수 없음.
:   251인 경우 포워드를 뜻하고 아래와 같은 형식으로 포워드 메일주소를 Receiver가 보내줌
:   251 User not local; will forward to <Jones@USC-ISI.ARPA>\r\n
:   각 응답코드에 대해서는 rfc821 문서를 참고.
:
: 6. 아래 메시지를 Receiver에게 보냅니다.
:    DATA\r\n
:    이에 대해 Receiver가 354가 아닌 응답코드를 보내면 메일을 보낼 수 없음.
:    Receiver가 354 응답코드를 보낼 때는 아래와 같이 메일의 끝을 지정하는 방법을 같이 보냅니다.
:    아래의 경우 메일 내용을 Receiver가 수신받는 중에 C언어 문자열로 말하자면 "\r\n.\r\n"을 만나면 그게 메일의 끝표시로 간주하겠다는 뜻입니다.
:    따라서 보내는 쪽에서는 메일끝에 "\r\n.\r\n"를 추가로 보내면 되는 것이지요. 보통 이것을 사용합니다.
:    354 Start mail input; end with <CRLF>.<CRLF>\r\n
:   
: 7. 메일 내용(메일헤더 등 메일의 모든 내용)을 보냅니다.
:
: 8. 메일의 내용을 다 보냈으면 끝표시를 보냅니다.
:   위 예의 경우 "\r\n.\r\n"를 보냅니다.
:   Receiver는 아래 응답을 보낼 것입니다.
:   250 OK\r\n
:  
: 9. 마지막으로 종료 메시지를 보냅니다.
:   QUIT\r\n
:   Receiver는 이에 대해 아래와 같은 형식의 응답 메시지를 보냅니다.
:   221 USC-ISIF.ARPA Service closing transmission channel\r\n
:  
: 10. TCP 커넥션을 끊습니다.
:
:
: 참고로, 메일 내용을 어떻게 구성해야 하는지는,
: 어떤 메일이든 하나 골라서 파일로 저장한 다음
: 텍스트 편집기로 열어보면 그 구조가 모두 나와 있으므로 이를 참고하면 됩니다.
: 한편, 첨부 파일 등 ASCII 코드 범위를 벗어난 Byte가 있는 경우는 인코딩을 해야하는데 보통 Base64 인코딩을 사용합니다. 제목에 한글이 있는 경우와 첨부파일은 인코딩해야 한다고 보면 됩니다.
:
:
: /////////////////////////////////////////////////////////////////////////
: void __fastcall TSendMailThread::Execute()
: {
:   CSock1 = new TClientSocket(NULL);
:   CSock1->Active=false;
:   CSock1->ClientType=ctBlocking;
:   CSock1->Port=25;
:   CSock1->OnConnect = ClientSocket1Connect;
:    CSock1->Host=Mail->ReceiverSMTP;
:    CSock1->Open();
: .
: .
: .
:
: }
:
: /////////////////////////////////////////////////////////////////////////
: void __fastcall TSendMailThread::ClientSocket1Connect(TObject *Sender,
:       TCustomWinSocket *Socket)
: {
:   SendMail();
: }
:
: /////////////////////////////////////////////////////////////////////////
: int __fastcall TSendMailThread::SendMail()
: {
:  String toAddress;
:  String rep="";
:  int repCode;
:  String body;
:  TReceiver *receiver;
:
:   if(!CSock1) return -1;
:
:   toAddress = receiver->Id + "@" + Mail->ReceiverDomain;
:
:   Completed=false;
:
:   pStream = new TWinSocketStream(CSock1->Socket, 30000);
:   try
:   {
:     while (!Terminated && CSock1->Active)
:     {
:       try
:       {
:         rep = GetReply();
:         if(rep.IsEmpty()) ;
:         if(!extractReplyCode(rep,repCode)) ;
:
:         if(repCode!=220)
:         {
:          receiver->Success=false;
:          receiver->TryLater=true;
:          receiver->ResultCode=repCode;
:          return repCode;
:         }
:
:         SendMessage("HELO " + Mail->SenderSMTP + "\r\n");
:         rep = GetReply();
:         if(rep.IsEmpty()) ;
:         if(!extractReplyCode(rep,repCode)) ;
:
:         if(repCode!=250)
:         {
:          receiver->Success=false;
:          receiver->TryLater=true;
:          receiver->ResultCode=repCode;
:          return repCode;
:         }
:
:         SendMessage(String("MAIL FROM: ") + "<" + Mail->From + ">\r\n");
:         rep = GetReply();
:         if(rep.IsEmpty()) ;
:         if(!extractReplyCode(rep,repCode)) ;
:
:         if(repCode!=250)
:         {
:          receiver->Success=false;
:          receiver->ResultCode=repCode;
:
:          if(repCode==500 || repCode==501 || repCode==421)
:          {
:            receiver->TryLater=false;
:          }
:          else
:          {
:            receiver->TryLater=true;
:          }
:          return repCode;
:         }
:
:         SendMessage(String("RCPT TO: ") + "<" + toAddress + ">\r\n");
:         rep = GetReply();
:         if(rep.IsEmpty()) ;
:         if(!extractReplyCode(rep,repCode)) ;
:
:         if(repCode!=250 && repCode!=251)
:         {
:          receiver->Success=false;
:          receiver->TryLater=false;
:          receiver->ResultCode=repCode;
:          if(repCode==550)
:          {
:          }
:          else if(repCode==551)
:          {
:            Mail->NewReceiverAddress=GetAddress(rep);
:          }
:          else if((repCode>=500 && repCode<=504) || repCode==553)
:          {
:          }
:          else if(repCode==552 || repCode==450 ||repCode==451 ||repCode==452)
:          {
:            receiver->TryLater=true;
:          }
:          else
:          {
:            receiver->TryLater=true;
:          }
:          return repCode;
:         }
:
:         SendMessage(String("DATA\r\n"));
:         rep = GetReply();
:         if(rep.IsEmpty()) ;
:         if(!extractReplyCode(rep,repCode)) ;
:
:         if(repCode!=354)
:         {
:          receiver->Success=false;
:          receiver->TryLater=true;
:          receiver->ResultCode=repCode;
:          return repCode;
:         }
:
:         body= "To: " + toAddress + " <" + toAddress + ">\r\n";
:         body=body+Mail->Headers;
:         body = body + Mail->Body1;
:         body = body + Mail->Body3 + Mail->Attachment + "\r\n.\r\n";
:
:         SendMessageBody(body);
:
:         rep = GetReply();
:         if(rep.IsEmpty()) ;
:         if(!extractReplyCode(rep,repCode)) ;
:
:         if(repCode!=250)
:         {
:          receiver->Success=false;
:          receiver->TryLater=true;
:          receiver->ResultCode=repCode;
:          return repCode;
:         }
:
:         SendMessage("QUIT\r\n");
:         rep = GetReply();
:         if(rep.IsEmpty()) ;
:         if(!extractReplyCode(rep,repCode)) ;
:
:         CSock1->Close();
:
:         receiver->Success=true;
:         receiver->TryLater=false;
:         receiver->ResultCode=repCode;
:         return 0;
:       }
:       catch (Exception &e)
:       {
:        //ShowMessage(e.Message);
:        CSock1->Close();
:        return -1;
:       }
:     }
:   }
:   __finally
:   {
:     delete pStream;
:   }
:
:   return 0;
: }
:
:
: /////////////////////////////////////////////////////////////////////////
: void __fastcall TSendMailThread::SendMessage(const String& msg)
: {
:   pStream->Write(msg.c_str(), msg.Length());
: }
:
: /////////////////////////////////////////////////////////////////////////
: String __fastcall TSendMailThread::GetReply(void)
: {
:   char buffer[1024];
:   memset(buffer, 0, 1024);
:   if(pStream->WaitForData(10000))
:   {
:       if(pStream->Read(buffer, 1024) == 0)
:       {
:          CSock1->Close();
:       }
:       return String(buffer);
:   }
:   else
:   {
:      CSock1->Close();
:      return "";
:   }
:   return String(buffer);
: }

감사합니다.
어디에 쓰려고 하는게 아니구요...
그냥 순수히 학문적인 취지에서 질문한 겁니다.
궁금해 하시는 것처럼... 어디(?)에 쓰지는 않을겁니다.
빌더에 있는 smtp 컴퍼넌트를 사용해서는 성공을 했는데, smtp 서버없이는 어떻게 될까?하고 궁금해서 질문을 올린겁니다.
답변 감사드리구요.. 좋은 하루되세요.

+ -

관련 글 리스트
37524 [SMTP] SMTP 서버 없이 전송되게 하는 코드나 컴포넌트가 있을까요? 초보자 850 2004/10/07
37529     Re:[SMTP] SMTP 서버 없이 전송되게 하는 코드나 컴포넌트가 있을까요? 임문환.실업자 1102 2004/10/07
37533         Re:Re:[SMTP] SMTP 서버 없이 전송되게 하는 코드나 컴포넌트가 있을까요? 초보자 1330 2004/10/07
37535             Re:Re:Re:[SMTP] SMTP 서버 없이 전송되게 하는 코드나 컴포넌트가 있을까요? 멀더 1062 2004/10/08
37540                 Re:Re:Re:Re:[SMTP] SMTP 서버 없이 전송되게 하는 코드나 컴포넌트가 있을까요? 초보자 1316 2004/10/08
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.