>php教程 >PHP开发 >소켓(php)을 사용하여 이메일 보내기

소켓(php)을 사용하여 이메일 보내기

高洛峰
高洛峰원래의
2016-12-02 10:12:151179검색

소켓 프로그래밍 소개
저는 TCP/IP 프로그래밍 전문가가 아니기 때문에 여기서는 제가 이해하고 경험한 내용을 공유하고 있음을 여러분께 말씀드리고 싶습니다.

fsockopen 함수를 사용하여 인터넷 연결을 엽니다. 함수 구문 형식은 다음과 같습니다.

int fsockopen(string 호스트 이름, int 포트, int [errno], string [errstr], int [timeout] ]);

여기서는 SMTP 프로토콜을 사용하므로 포트번호는 25 이므로 매개변수의 의미를 따로 이야기할 필요는 없을 것 같습니다. 연결이 성공적으로 열리면 파일 핸들처럼 사용할 수 있는
소켓 핸들이 반환됩니다. 사용 가능한 작업에는 fputs(), fgets(), feof(), fclose()
등이 포함됩니다.

아주 간단한 소개는 여기까지입니다.

SMTP의 기본
TCP/IP 기반 인터넷 프로토콜의 일반적인 명령 형식은 요청/응답 방식으로 구현되며, 모든 텍스트 정보를 사용하므로
처리가 더 쉽습니다. SMTP는 클라이언트가 서버에 이메일을 보낼 수 있도록 하는 Simple Mail Transfer Protocol의 약어입니다. 그래서
아래 명령어는 클라이언트가 서버에 요청 명령을 보내는 것을 의미하고, 응답은 서버가 클라이언트에게 반환하는 정보를 의미합니다.

SMTP는 명령 헤더와 메시지 본문의 두 부분으로 나뉩니다. 명령 헤더는 주로 클라이언트와 서버 간의 연결, 확인 등을 완료합니다. 전체 프로세스는 여러 명령
으로 구성됩니다. 각 명령이 서버로 전송된 후 서버는 일반적으로 3자리 응답 코드와 응답 텍스트로 구성된 응답 정보를 제공합니다. 여러 서버에서 반환되는 응답 코드는
프로토콜을 준수하지만 응답 텍스트는 그렇지 않습니다. 각 명령과 응답 끝에는 캐리지 리턴 문자가 있으므로 fputs() 및 fgets()를 사용하여 명령과 응답을 처리할 수 있습니다. SMTP 명령 및 응답 메시지는 한 줄입니다. 메시지 본문은 이메일
의 본문 부분이며, 마지막 끝줄은 끝줄과 같이 별도의 "."이어야 합니다.

클라이언트에서 일반적으로 사용되는 SMTP 명령은 다음과 같습니다.

HELO 호스트 이름: 서버에 인사하고 클라이언트에 사용된 컴퓨터 이름을 알려줍니다. 부담 없이 입력할 수 있습니다.

MAIL FROM: sender_id : 서버에게 보내라고 지시받는 사람의 주소
RCPT TO: receive_id: 서버에 받는 사람의 주소를 알려준다
DATA: 편지의 내용은 아래로 전송되며 특수한 줄로 끝납니다.
RESET: 이전 명령을 취소하고 다시 시작합니다.
사용자 ID 확인: 계정이 존재하는지 확인합니다(이 명령은 선택 사항이며 서버에서 지원하지 않을 수 있습니다).
QUIT: 연결을 종료합니다. end
서버가 반환하는 응답 정보(형식: 응답 코드 + 공백 + 설명) :

220 Service Ready(소켓 연결 성공 시 이 정보가 반환됨)

221 처리 중
250 요청한 이메일 작업이 정확하고 완료되었습니다(HELO, MAIL FROM, RCPT TO , QUIT 명령이 성공적으로 실행되면 이 정보가 반환됩니다)
354 데이터 전송을 시작하고 로 끝납니다. DATA 명령이 성공적으로 실행되면 반환됩니다. 클라이언트는 정보를 보내야 합니다.
500 구문 오류, 명령을 인식할 수 없습니다.
550 명령을 실행할 수 없으며 사서함이 유효하지 않습니다.
552 인터럽트 처리: 사용자가 파일 공간을 초과했습니다.
아래에 간단한 명령 헤더가 제공됩니다(소켓을 연 후 완료됨). stmp.263.net으로 이메일을 보냅니다. 테스트 결과:

HELO limodou

250 smtp.263.net
MAIL FROM: chatme@263.net
250 Ok
RCPT TO: chatme@263.net
250 Ok
DATA
354 End data with .
받는 사람: chatme@263.net
보낸 사람: chatme@263.net
제목: test
보낸 사람: chatme@263.net
test
종료합니다.
250 Ok: C46411C5097E0으로 대기

 이것은 SMTP에 대한 간단한 지식입니다. 관련 내용은 RFC에서 찾을 수 있습니다.

RFC 821은 이메일 수신/발신 관련 명령을 정의합니다.

RFC 822는 이메일을 지정합니까?

RFC 2045-2048은 멀티미디어 이메일을 지정합니까?
RFC 1113, 1422-1424는 이메일 섹스의 기밀성을 향상시키는 방법을 논의합니다.

send_mail 클래스 구현

이제 제가 작성한 메일 보내기 클래스를 소개하겠습니다. 위의 준비 지식을 바탕으로 구현은 다음과 같습니다.


클래스의 멤버 변수

var $lastmessage; //반환된 마지막 응답 메시지를 기록합니다.

var $lastact; //문자열 형식의 마지막 작업

var $ Welcome ; //HELO 뒤에 사용되는 사용자는 환영합니다.
var $debug; //디버깅 정보 표시 여부
var $smtp; //smtp 서버
var $port 번호
var $fp; //소켓 핸들

그 중 $lastmessage와 $lastact는 오류가 발생했을 때 마지막 응답 정보와 실행된 명령을 기록하는 데 사용됩니다

. 테스트를 위해 $debug 변수도 정의했습니다. 해당 값이 true이면 실행 프로세스 중에 일부 실행 정보가 표시되고, 그렇지 않으면 출력이

없습니다. $fp는 열린 소켓 핸들을 저장하는 데 사용됩니다.

수업 구성


------------------------------- ------ ----------
함수 send_mail($smtp , $welcome="" , $debug=false)
{
if(empty($smtp)) die("SMTP는 NULL일 수 없습니다!")
$this->smtp=$smtp ;
if( 비어 있음($welcome))
{
$this->welcome=gethostbyaddr("localhost")
}
else
$this->welcome =$환영
$this->debug=$debug;
$this->lastmessage=""
$this->lastact=""; ;port="25" ;
}
-------------------------------------- ------------ ------------------------- -------
이 생성자는 주로 일부 초기값 결정 및 설정을 완료합니다. $welcome은 HELO 지시문에서 서버에 사용자 이름을 알려주는 데 사용됩니다.
HELO 명령에는 컴퓨터 이름이 필요하지만 컴퓨터 이름 없이도 사용할 수 있습니다. 사용자가 $welcome을 제공하지 않으면 로컬 컴퓨터 이름이 자동으로 검색됩니다.

디버깅 정보 표시

---------------------- - ------------------

1개 함수 show_debug ($message, $inout)
2 {
3 if ($this->debug)
4 {
5 if($inout=="in") //응답 정보
6 {
7 $m='<<
8 }
9 else
10 $m='>> "n$", $message))
12 $message .= "
"
13 $message=nl2br($message)
14 echo "";
15 }
16 }
---------------------- ----- ------------------- ----- ----------
이 함수는 디버깅 정보를 표시하는 데 사용됩니다. 업로드 명령인지 반환된 응답인지 $inout에서 지정할 수 있습니다.
반환된 응답인 경우 "out"을 사용합니다.

3번째 줄은 디버깅 정보 출력 여부를 결정합니다.

5번째 줄에서는 응답 메시지인지 확인합니다. 그렇다면 7번째 줄의 정보 앞에 ">"를 추가하여 정보를 구분합니다. 그렇지 않으면 10번째 줄에 ">"를 추가합니다. " 업로드 지침을 구별합니다.

11-12행은 정보 문자열의 마지막 행이 개행 문자인지 여부를 결정합니다. 그렇지 않은 경우 HTML 개행 표시를 추가합니다. 13행은 모든 개행 문자를 HTML
  개행 태그로 변환합니다.
14번째 줄, 전체 메시지를 출력하고 메시지 색상을 회색으로 설정하여 차이점을 보여줍니다.

명령 실행

-------------------------------- --------------

1 함수 do_command($command, $code)

2 {
3 $this->lastact=$command;
4 $this->show_debug($this->lastact, "out ")
5 fputs ( $this->fp, $this->lalastact )
6 $this->lastmessage = fgets ( $this->fp, 512 )
7 $this->show_debug( $this->lastmessage, "in");
8 if(!ereg("^$code", $this->lastmessage))
9 {
10 return false; 11 }
12 else
13 return true
14 }
--------------- ------------------------------------------------ -- --------
소켓 처리 부분을 작성하면서 HELO, MAIL FROM, RCPT TO, QUIT, DATA 명령 등 일부 명령의 처리가 매우 유사하다는 것을 발견했습니다.
표시 여부에 따라 디버깅이 필요합니다. 동시에 반환된 응답 코드가 예상되는 경우 처리를 계속해야 합니다.
예상하지 않는 경우 처리를 중단해야 합니다. 따라서 명확성과 단순화를 위해 이러한 명령을 처리하기 위해 일반 처리 기능이 특별히 작성되었습니다.
함수 매개변수의 $code는 예상되는 응답 코드입니다. 응답 코드가 동일하면 처리가 성공한 것이고, 그렇지 않으면 오류가 발생합니다.

3번째 줄은 마지막으로 실행된 명령을 기록합니다.
4번째 줄에는 업로드 명령이 표시됩니다.
5번째 줄은 fputs를 사용하여 실제로 명령을 서버에 전송합니다.

6번째 줄, 서버로부터 받은 응답 정보는 마지막 응답 메시지 변수에 들어갑니다.

7번째 줄에는 응답 정보가 표시됩니다.
8행은 응답 정보가 예상되는지 여부를 결정합니다. 그렇다면 13행은 성공(true)을 반환하고, 그렇지 않으면 10행은 실패(false)를 반환합니다.

이와 같이 이 함수는 한편으로는 지침과 정보를 전송하고 표시하는 기능을 완성하는 동시에, 다른 한편으로는 반환된 응답이 성공적인지 여부를 판단합니다.

이메일 발송처리

아래 내용이 진짜 비밀인데 잘 읽어보셔야 합니다. :)

---------------------------------- --------------------------------- 
1개의 함수 보내기( $to,$from,$subject,$ 메시지) 
2 { 

4 //连接服务器 
5 $this->lastact="connect"; 

7 $this->show_debug("SMTP 서버에 연결: ".$this->smtp, "out"); 
8 $this->fp = fsockopen ( $this->smtp, $this->port ); 
9 if ( $this->fp ) 
10 { 
11 
12 set_socket_blocking( $this->fp, true ); 
13 $this->lastmessage=fgets($this->fp,512); 
14 $this->show_debug($this->lastmessage, "in"); 
15 
16 if (! ereg ( "^220", $this->lastmessage ) ) 
17 { 
18 return false; 
19 } 
그 외 20개 
21 { 
22 $this->lastact="HELO " . $this->환영합니다. "N"; 
23 if(!$this->do_command($this->lastact, "250")) 
24 { 
25 fclose($this->fp); 
26개는 false를 반환합니다. 
27 } 
28 
29 $this->lastact="메일 보낸 사람: $from" . "N"; 
30 if(!$this->do_command($this->lastact, "250")) 
31 { 
32 fclose($this->fp); 
33은 false를 반환합니다. 
34 } 
35 
36 $this->lastact="RCPT 대상: $to" . "N"; 
37 if(!$this->do_command($this->lastact, "250")) 
38 { 
39 fclose($this->fp); 
40은 false를 반환합니다. 
41 } 
42 
43 //发送正文 
44 $this->lastact="DATAn"; 
45 if(!$this->do_command($this->lastact, "354")) 
46 { 
47 fclose($this->fp); 
48은 false를 반환합니다. 
49 } 
50 
51 //处理Subject头 
52 $head="제목: $subjectn"; 
53 if(!empty($subject) && !ereg($head, $message)) 
54 { 
55 $message = $head.$message; 
56 } 
57 
58 //处理From头 
59 $head="From: $fromn"; 
60 if(!empty($from) && !ereg($head, $message)) 
61 { 
62 $message = $head.$message; 
63 } 
64 
65 //处理 To头 
66 $head="받는 사람: $ton"; 
67 if(!empty($to) && !ereg($head, $message)) 
68 { 
69 $message = $head.$message; 
70 } 
71 
72 //加上结束串 
73 if(!ereg("n.n", $message)) 
74 $message .= "n.n"; 
75 $this->show_debug($message, "out"); 
76 fputs($this->fp, $message); 
77 
78 $this->lastact="QUITn"; 
79 if(!$this->do_command($this->lastact, "250")) 
80 { 
81 fclose($this->fp); 
82는 false를 반환합니다. 
83 } 
84 } 
85 true를 반환합니다. 
86 } 
87 else 
88 { 
89 $this->show_debug("연결 실패!", "in"); 
90은 false를 반환합니다. 
91 } 
92 } 
------------------------- ------------------------------ 
  有些의미思很清楚내 마음은 그렇지 않습니다.

  这个函数一共有 4个参数,分别是$to表示收信人,$from表示发信人,$subject表求邮件主题和$mes 세이지
表示邮件体。如果处理成功则返回true,失败则返回false。

8번째 줄, 메일 서버에 연결합니다. 성공하면 응답 코드는 220이 됩니다.
라인 12는 차단 모드를 설정하여 계속하기 전에 정보를 반환해야 함을 나타냅니다. 자세한 지침은 설명서를 참조하세요.
16행, 응답 코드가 220인지 확인합니다. 그렇다면 계속 처리하고, 그렇지 않으면 오류가 반환됩니다.
22-27행은 HELO 명령을 처리하며 예상 응답 코드는 250입니다.
29-34행은 MAIL FROM 명령을 처리하며 예상 응답 코드는 250입니다.
36-41행은 RCPT TO 명령어를 처리하며 예상 응답 코드는 250입니다.
44-49행은 DATA 명령을 처리하며 예상 응답 코드는 354입니다.
51-76행, 이메일 본문을 생성하여 보냅니다.
52~56행, $subject가 비어 있지 않으면 이메일 본문에 제목 부분이 있는지 확인하고, 없으면 제목 부분을 추가합니다.
59-63행, $from이 비어 있지 않은 경우 이메일 본문에 보낸 사람 부분이 있는지 확인합니다. 그렇지 않은 경우 보낸 사람 부분을 추가합니다.
66-70행, $to가 비어 있지 않으면 이메일 본문에 수신자 부분이 있는지 확인합니다. 그렇지 않은 경우 수신자 부분을 추가합니다.
73~74행, 이메일 본문에 끝줄이 있는지 확인하고, 없으면 이메일 본문 끝줄을 추가합니다(별도의 줄로 특수줄 "." 포함).
76번째 줄, 이메일 본문을 보냅니다.
78-83행은 QUIT를 실행하여 서버와의 연결을 종료합니다. 예상 응답 코드는 250입니다.
85행에서는 처리 성공 플래그(true)를 반환합니다.
81-91행, 서버 연결 실패 처리.

위의 내용은 send_mail 클래스 전체를 구현한 것인데 어렵지 않을 것입니다. 아래에 예가 나와 있습니다.

이메일 전송 예시
가장 간단한 예시를 먼저 들어보겠습니다.
---------------------------- ------------------------------------- ----
1 include "sendmail.class.php3"
2 $email="안녕하세요, 테스트 편지입니다!"
3 $sendmail=new send_mail ("smtp.263.net", "limodou", true); //디버깅 정보 표시
4 if($sendmail->send("chatme@263.net", "chatme@263.net" , "test", $email))
5 {
6 echo "성공적으로 전송되었습니다!
"
7 }
8 else
9 {
10 echo " 전송 실패!
11 }
?>
------------ - ------------------------------------------------- - --
1행, send_mail 클래스를 로드합니다.
3행에서는 클래스 인스턴스를 만들고 표시 정보를 설정합니다.
$sendmail=new send_mail("smtp.263.net");.
4번째 줄, 이메일을 보내세요.


정말 간단하죠? 다음으로는 앞선 MIME 이메일 전송 예시를 바탕으로 HTML 첨부파일 전송 예시를 보여드리겠습니다.

------------------------------- ------ ----------

include "MIME.class.php3";
//참고로 MIME 이메일 전송에 관한 기사에서 이 클래스 파일 이름은 MIME.class로 변경되었습니다.

$to = 'chatme @263.net'; //받는 사람의 이메일 주소로 변경됨
$str = "Newsletter for ".date('M Y', time());

//정보가 내가 변경했습니다
$html_data = '''

안녕하세요!

';

//MIME 클래스 인스턴스 생성
$mime = new MIME_mail(" chatme@263.net", $to, $str);

//HTML 첨부 파일 추가
$mime->attach($html_data, "", HTML, BASE64);

//주석 처리하고 내 보내는 이메일 처리 사용
//$mime->send_mail();

//이메일 생성
$mime-> ;gen_email();

//이메일 정보 표시
//echo $mime->email."
";

//sendmail 파일 포함
include "sendmail.class.php3";

//인스턴스 생성
$sendmail=new send_mail("smtp.263.net", "limodou", true);

/ /메일 보내기
$sendmail->send("chatme@263.net", "chatme@263.net", $str, $mime->email);

?>


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.