웹마스터 팁
XE를 이용하여 SMTP 보내보기[개발자용]
2011.11.02 21:05
들어가기전에
오랜만에 팁을 올려봅니다. 해당 팁은 기존 XE Core에서 이용되는 mail()함수를 통한 이용방법이 아닌 별도의 SMTP 서버를 이용하여 전송할 수 있도록 해주는 팁 입니다.XE mail과 다른점
기존 방식에 문제점은 mail()를 이용하기 때문에 메일이 도착하지 못하는 경우가 발생하고 외부메일을 이용한 방식이 불가하다는 점 입니다. 이를 개선하여 어디든 도착가능 하도록하고 외부메일(gmail 등)의 SSL 인증 방식을 통해 서버내에 메일이 동작하지 않더라도 타 기관의 SMTP 서버를 통해 메일을 보낼 수 있습니다.주의점
- 앞으로 설명할 내용은 개발자용의 소스인지라 일반인들이 적용하기엔 무리가 따를 수 있습니다.- mail()가 아닌 fsockopen() 방식을 사용합니다. 본인의 호스팅이 각 기관(예 gmail) 경로로의 접근이 막혀있다면 외부경로로 하셔도 접근이 안되실 수 있습니다.
- 사설 ip의 경우 본인 컴에 sendmail 등을 올려도 메일발송이 안될 수가 있습니다.
소스
/** * @brief 메일 보내기 전 정보 초기화 **/ function sendMail($args = false) { $oModuleModel = &getModel('module'); $mail = new Mail; $mail->smtp_secure = 'ssl'; //일반 sendmail은 'tcp' $mail->smtp_server = '+ 'smtp.gmail.com'; $mail->smtp_port = '465'; $mail->user = 'gmail메일주소'; $mail->pass = '패스워드'; $mail->setSender($args->sender->name,$args->sender->email); $mail->setTitle($args->title); $mail->setContent($args->content); $mail->setContentType('html'); // 첨부파일 정리 if(is_array($args->attach)) { foreach($args->attach as $key => $attach) { $mail->attach[] = $attach; } } // 메일 보냄 foreach($args->receiptor as $key => $receiptors) { $mail->setReceiptor($receiptors->name, $receiptors->email); $this->_sendMail($mail); } } /** * @brief 메일 보내기 **/ function _sendMail($mail) { // 영문이외의 문자 이름이 출력되도록 함 $sender_email = sprintf("%s <%s>", '=?utf-8?b?'.base64_encode($mail->sender_name).'?= ', $mail->sender_email); $receiptor_email = sprintf("%s <%s>", '=?utf-8?b?'.base64_encode($mail->receiptor_name).'?= '+ ', $mail->receiptor_email); $boundary = "----==".uniqid(rand(),true); // 바운드를 초기화한다 $eol = $GLOBALS['_qmail_compatibility'] == 'Y' ? "\n" : "\r\n"; $headers = sprintf( "MIME-Version: 1.0".$eol. "Content-Type: Multipart/mixed;".$eol."\tboundary=\"%s\"".$eol. "Subject: %s".$eol. "From: %s".$eol. "To: %s".$eol.$eol, $boundary, $mail->getTitle(), $sender_email, $receiptor_email ); $body = sprintf( "--%s".$eol. "Content-Type: text/html; charset=utf-8".$eol. "Content-Transfer-Encoding: base64".$eol.$eol. "%s".$eol.$eol, $boundary, $mail->getHTMLContent() ); // 첨부파일 if(is_array($mail->attach)) { foreach($mail->attach as $key => $path) { $name = basename($path->filename); $file = FileHandler::readFile($path->fileurl); $fileBody = sprintf( "--%s".$eol. "Content-Type: application/octet-stream".$eol. "Content-Transfer-Encoding: base64".$eol. "Content-Disposition: attachment; filename=\"%s\"".$eol.$eol. "%s", $boundary, $name, chunk_split(base64_encode($file)) ); $body .= $fileBody; } } // 인증방식으로 메일을 보냄 if($smtp_socket = @fsockopen($mail->smtp_secure."://".$mail->smtp_server, $mail->smtp_port, $errno, $errstr, 5)) { $this->_getMail($smtp_socket); @fputs($smtp_socket, 'HELO '.$mail->smtp_secure."://".$mail->smtp_server.$eol); $this->_getMail($smtp_socket); @fputs($smtp_socket, 'AUTH LOGIN'.$eol); $this->_getMail($smtp_socket); @fputs($smtp_socket, base64_encode($mail->user).$eol); $this->_getMail($smtp_socket); @fputs($smtp_socket, base64_encode($mail->pass).$eol); $this->_getMail($smtp_socket); @fputs($smtp_socket, 'MAIL From: <'.$mail->sender_email.'>'.$eol); $this->_getMail($smtp_socket); @fputs($smtp_socket, 'RCPT To: <'.$mail->receiptor_email.'>'.$eol); $this->_getMail($smtp_socket); @fputs($smtp_socket, 'DATA'.$eol); $this->_getMail($smtp_socket); $content = sprintf( "%s".$eol. "%s".$eol. ".".$eol, $headers, $body ); @fputs($smtp_socket, $content); $this->_getMail($smtp_socket); @fputs($smtp_socket, 'QUIT'.$eol); @fclose($smtp_socket); } } /** * @brief 상대방의 응답을 기다립니다.(gmail등 인증 방식 사용시) **/ function _getMail($socket = null) { if(!$socket) return; $i = 0; $response = '-'; while($response == '-' && $i<10) { $response = @fgets($socket, 256); if($response) $response = substr($response,3,1); else return; $i++; } } /** * @brief SMTP 서버가 동작하는지 체크 **/ function procNmsCheckSmtp() { // 일반 sendmail은 ssl이 아니라 tcp if($smtp_socket = @fsockopen('ssl'."://".'smtp.gmail.com', '465', $errno, $errstr, 5)) { $message = @fgets($smtp_socket, 512); @fclose($smtp_socket); } if(!preg_match("/SMTP/", $message)) return 'error'; return '+ 'complete'; }
수행
echo procNmsCheckSmtp(); $mail->sender->name = '보내는이름'; $mail->sender->email = '보내는메일주소'; $mail->title = '제목'; $mail->content = '내용'; $mail->receiptor[0]->name = '받는사람이름'+ '; $mail->receiptor[0]->email = '받는사람메일주소'; $mail->attach[0]->fileurl = '경로/파일명'; $mail->attach[0]->filename = '파일이름'; sendMail($mail);
마무리
소스가 뭔가 이상하고 봐도 어렵죠? 실은 nmsXE에 적용했던 소스입니다. 제가 gmail을 통해 네이버, 다음 등 주요 포탈과 호스팅 계정 등으로 첨부파일 포함하여 전송확인은 했는데 예전 집이 사설ip여서 sendmail을 올려도 되질 못하여 내놓을 수 없다가 이번에 되는걸 확인하고 팁으로 적어보았습니다. 설명도 부족하고 개발자들이 보셔도 잘 사용할지 못할지 모르겠지만 위와 같은 형식으로 사용하시면 기존에 메일을 발송해도 못받으시거나 하던 문제는 해결 됩니다.
나중에 따로 배포본으로 만들어서 자료실에 올리던가 해야겠습니다. 하지만 위 기능하나만 가지고 내는건 뭐해서 제가 제작하는 모듈에 알림이 기능으로써 각각 집어넣을지 단체메일링 같은 좀 살을 붙여서 모듈로 배포할지는 고민중입니다.
- [2016/10/17] 묻고답하기 https 관련 질문입니다 ㅠㅠ *1
- [2016/04/26] 묻고답하기 회원가입(휴대폰인증모듈)페이지 속도 문제.. *3
- [2016/04/13] 웹마스터 팁 IIS에서 HTTPS를 사용하기 위한 SSL설정 (letsencrypt 인증서 설치, 갱신)
- [2016/03/18] 묻고답하기 SSL 테스트, B등급에서 더 올릴 수 있나요? *2
- [2016/01/07] 묻고답하기 ssl 항상사용 후 접근이 안되고 있습니다.. *5
댓글 10
-
tobor
2011.11.02 22:20
-
tobor
2011.11.03 01:01
gmail등 ssl이용한 smtp사용시 extension 모듈인 php_openssl 로드 되어 있어야하는데 대부분의 호스팅 회사들은 php_openssl 로드하지 않고있습니다.^^;
-
제 호스팅은 올라가있네요. ^^ 만약 그런 이유로 ssl이 안된다하시면 tcp로 접근되는 SMTP로 사용하시면 되겠네요.
-
똑디
2011.11.02 22:37
언젠가는 단체메일링 기능이 나오겠네요. 기대해 봅니다.
-
snows96
2011.11.03 21:26
그런데 사설IP라 함은 광랜 등등 가정에서 사용하는 인터넷 아닌가요???
희안하게 전 저런외부 SMTP사용하지 않고서도 그냥 sendmail같은 서버자체 메일서버로 메일보내버려도 정상발송되어 포털사이트에 스팸메일함도 아닌 받은메일함에 당당하게 자리하고 있던데요....? 어떻게 된 거죠????
-
mail() 함수가 아니라 sendmail을 통해 보내서 그런가보죠. 메일에 제목, 메시지 말고도 여러 기준의 포멧이 있는데 잘 지켜졌는가를 각 포탈들이 보고 대응하는 것 같습니다. 국내 광랜은 대부분 공인IP를 DHCP로 돌려가며 사용하고 있는걸로 아는데 사설도 많은가보군요.
-
snows96
2011.11.07 00:36
아, 광랜 자체가 공인IP이군요... 전 유동IP처럼 가정인터넷 자체가 사설인 줄 알았는데.... 무조건 고정IP만 공인이라 생각하고...... (하긴, 유동IP더라도 받았던 IP주소 그대로 바뀌기 전에 외부에서 치면 접속되는 걸 보아선.....) 단, 인터넷선 공유해서 PC가 여러대 물려있는데 서버만 특별히 DMZ설정을 해 놓아서 외부에서 받은게 공인인거라면 공인받은거나 다름없죠.
저의 경우에는 sendmail 설치되어있고 XE코어에서 자체적으로 보내는 E-mail(메일인증, 비번찾기)을 테스트 하였는데 그럼 XE는 서버에 설치된 메일 서버를 통해 보내는건가요? (예전에 메일서버 없을 때 발송안되었던 기억으론...) 그리고 어떤 외부모듈 중에는 또 mail()이라는 함수를 쓰는게 있나 보군요.....
-
Hide_D
2011.11.03 22:39
아뇨 사설 IP는
192.168.*.*로 주로 공유기를 사용하는 가정에서 흔히 볼 수 있는 주소를 말합니다.
-
snows96
2011.11.07 00:38
그렇군요..... 라르게덴님께서도 광랜은 DHCP로 "공인IP"를 돌려가며 사용하는 것일거라고 해놓으셨더군요...... 전 고정IP아니면 (유동이면)다 사설인 줄 알았습니다. ㅎㅎ
물론 집에서 공유기를 사용하여 PC여러대를 몰려놓지만 서버에 DMZ설정을 해놓아서 외부IP가 공인이라면 서버는 공인IP사용하는거나 마찬가지죠 ㅎㅎ
제목 | 글쓴이 | 날짜 |
---|---|---|
DB 용량 확보하기 [6] | 소렌트. | 2010.10.26 |
레이어가 뒤로 숨는 경우 레이아웃을 확인하세요! [1] | 아고라 | 2010.10.26 |
비밀번호 찾기 기능 조심하세요
[4]
![]() | 老姜君 | 2010.10.28 |
글읽기에서 글쓴이의 닉네임을 이름으로 변경하기 | 하얀마법 | 2010.10.29 |
IE 전용 페이지 전환시 부드럽게 하기 (퍼옴) [2] | 오실롯 | 2010.10.29 |
확장변수(textarea)에서 html 사용하기 [3] | 하늘종 | 2010.11.01 |
게시판에서는 파일첨부가 되는데 페이지모듈에서 파일첨부가 안 되시는 경우! [1] | sejin7940 | 2010.11.02 |
페이지 모듈에서 파일 업로드시 살아지는 현상 [1] | 조슈아킴 | 2010.11.02 |
''게시판 설명''에서 <br />에 margin이 먹는 버그 해결법 [1] | 지녁 | 2010.11.03 |
메인 페이지 수정이 안되는 경우
![]() | nurungso | 2010.11.07 |
스팸필터 단어 목록 (성인,불륜,화상채팅,만남 등등) [2] | 때린데 또때려 | 2010.11.08 |
큐브리드(CUBRID) 초보자 학습 자료 및 유용한 링크 정리
![]() | 면스판 | 2010.11.09 |
파일질라에서 html 파일 수정법 | 불패의초인 | 2010.11.11 |
관리자 메인페이지 카운터와 그래프 제거하기 [3] | 도라란 | 2010.11.15 |
XE 속도 0.0001초라도 올리는 소소한 팁들 (추가) [5] | 소렌트. | 2010.11.16 |
게시판 댓글에서 "이 댓글을..." 문구 없애는 방법 [3] | AlcoholJ | 2010.11.19 |
게시글 검색 [제목+내용]을 기본으로 하기 [2] | 깜빡이영어 | 2010.11.20 |
미궁속의 문제점 해결법(2가지) [2] | 박용식 | 2010.11.21 |
파일 첨부할때 HTTP Error 메세지 창이 뜨면서 첨부되지 않을때 해결방법
[1]
![]() | DuRi | 2010.11.22 |
앞으로 공용선택자 사용은 그만.... [5] | ForHanbi | 2010.11.23 |
중요한건 ssl 모듈이 로드되어야한다는것..