웹마스터 팁

들어가기전에

오랜만에 팁을 올려봅니다. 해당 팁은 기존 XE Core에서 이용되는 mail()함수를 통한 이용방법이 아닌 별도의 SMTP 서버를 이용하여 전송할 수 있도록 해주는 팁 입니다.

XE mail과 다른점

기존 방식에 문제점은 mail()를 이용하기 때문에 메일이 도착하지 못하는 경우가 발생하고 외부메일을 이용한 방식이 불가하다는 점 입니다. 이를 개선하여 어디든 도착가능 하도록하고 외부메일(gmail 등)의 SSL 인증 방식을 통해 서버내에 메일이 동작하지 않더라도 타 기관의 SMTP 서버를 통해 메일을 보낼 수 있습니다.

주의점

- 앞으로 설명할 내용은 개발자용의 소스인지라 일반인들이 적용하기엔 무리가 따를 수 있습니다.

- mail()가 아닌 fsockopen() 방식을 사용합니다. 본인의 호스팅이 각 기관(예 gmail) 경로로의 접근이 막혀있다면 외부경로로 하셔도 접근이 안되실 수 있습니다.
- 사설 ip의 경우 본인 컴에 sendmail 등을 올려도 메일발송이 안될 수가 있습니다.



소스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/**
 * @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';
}


수행

1
2
3
4
5
6
7
8
9
10
11
12
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을 올려도 되질 못하여 내놓을 수 없다가 이번에 되는걸 확인하고 팁으로 적어보았습니다. 설명도 부족하고 개발자들이 보셔도 잘 사용할지 못할지 모르겠지만 위와 같은 형식으로 사용하시면 기존에 메일을 발송해도 못받으시거나 하던 문제는 해결 됩니다.


나중에 따로 배포본으로 만들어서 자료실에 올리던가 해야겠습니다. 하지만 위 기능하나만 가지고 내는건 뭐해서 제가 제작하는 모듈에 알림이 기능으로써 각각 집어넣을지 단체메일링 같은 좀 살을 붙여서 모듈로 배포할지는 고민중입니다.

태그 연관 글
  1. [2016/10/17] 묻고답하기 https 관련 질문입니다 ㅠㅠ by 쿠닌 *1
  2. [2016/04/26] 묻고답하기 회원가입(휴대폰인증모듈)페이지 속도 문제.. by deok *3
  3. [2016/04/13] 웹마스터 팁 IIS에서 HTTPS를 사용하기 위한 SSL설정 (letsencrypt 인증서 설치, 갱신) by ehii
  4. [2016/03/18] 묻고답하기 SSL 테스트, B등급에서 더 올릴 수 있나요? by 마꼬꼬 *2
  5. [2016/01/07] 묻고답하기 ssl 항상사용 후 접근이 안되고 있습니다.. by 신다영 *5
제목 글쓴이 날짜
판교오피 ⦑오피사이트.NET⦒ 판교오피 판교출장마사지 판교오피 판교OP koykoyah 2025.02.22
안산오피 ⦑출장마사지안내.COM⦒ 안산오피 안산출장마사지 안산오피 안산OP koykoyah 2025.02.22
동두천오피 ⦑오피쓰주소.COM⦒ 동두천마사지 동두천오피 동두천오피 동두천OP koykoyah 2025.02.22
강서오피 강서오피 ⦑오피쓰.COM⦒ 강서OP 강서스파 강서오피 koykoyah 2025.02.22
판교오피 ⦑오피쓰.COM⦒ 판교OP 판교오피 판교출장샵 판교오피 koykoyah 2025.02.22
송탄오피 송탄OP ⦑오피쓰주소.COM⦒ 송탄휴게텔 송탄오피 송탄오피 koykoyah 2025.02.22
영등포오피 ⦑오피쓰.COM⦒ 영등포오피 영등포출장마사지 영등포오피 영등포OP koykoyah 2025.02.22
건대오피 건대출장안마 ⦑출장안마사이트.COM⦒ 건대OP 건대오피 건대오피 koykoyah 2025.02.22
안산오피 안산OP ⦑오피.CLUB⦒ 안산휴게텔 안산오피 안산오피 koykoyah 2025.02.22
용인오피 ⦑오피쓰주소.COM⦒ 용인오피 용인출장마사지 용인오피 용인OP koykoyah 2025.02.22
용인오피 용인OP ⦑출장마사지안내.COM⦒ 용인휴게텔 용인오피 용인오피 koykoyah 2025.02.22
동두천오피 ⦑오피사이트.NET⦒ 동두천오피 동두천OP 동두천건마 동두천오피 koykoyah 2025.02.22
해운대오피 ⦑오피사이트.NET⦒ 해운대오피 해운대출장마사지 해운대오피 해운대OP koykoyah 2025.02.22
수원오피 ⦑오피.CLUB⦒ 수원오피 수원OP 수원건마 수원오피 koykoyah 2025.02.22
제주도오피 제주도OP ⦑오피.CLUB⦒ 제주도휴게텔 제주도오피 제주도오피 koykoyah 2025.02.22
익산오피 익산오피 ⦑오피사이트.NET⦒ 익산OP 익산스파 익산오피 koykoyah 2025.02.22
동두천오피 ⦑출장안마사이트.COM⦒ 동두천오피 동두천OP 동두천건마 동두천오피 koykoyah 2025.02.22
인천오피 인천오피 ⦑오피쓰.COM⦒ 인천OP 인천스파 인천오피 koykoyah 2025.02.22
안양오피 ⦑오피사이트.NET⦒ 안양마사지 안양오피 안양오피 안양OP koykoyah 2025.02.22
일산오피 ⦑출장마사지안내.COM⦒ 일산오피 일산출장마사지 일산오피 일산OP koykoyah 2025.02.22