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
[37535] Re:Re:Re:[SMTP] SMTP 서버 없이 전송되게 하는 코드나 컴포넌트가 있을까요?
멀더 [mulder] 1062 읽음    2004-10-08 11:45
멀더입니다. 수정했습니다.

필요하신건 수신자메일도메인의 MX 호스트 값을 구하시면 됩니다.
MX 호스트를 구한다음 그호스트를 SMTP OutBound서버로 이용해
임문환님의 방법과 같이 SMTP 발송하시면 OK.
그러면 Relay용 SMTP outbound 서버가 필요없어 지지요...;)

참고 : http://cbuilder.borlandforum.com/impboard/impboard.dll?action=read&db=bcb_tutorial&no=58


초보자 님이 쓰신 글 :
: 임문환.실업자 님이 쓰신 글 :
: : 초보자 님이 쓰신 글 :
: : : 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 서버 없이 전송되게 하는 코드나 컴포넌트가 있을까요? 임문환.실업자 1103 2004/10/07
37533         Re:Re:[SMTP] SMTP 서버 없이 전송되게 하는 코드나 컴포넌트가 있을까요? 초보자 1331 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.