인터넷정보

php에서 첨부파일이 포함된 메일 보내기 함수

알 수 없는 사용자 2007. 10. 11. 22:08
/*=========================
함수 사용법
mail_fsend(받는사람,제목,메세지,추가해더,첨부할 파일)
참고 : 첨부할 파일은 메일이 발송되는 서버안에서의 파일임
참고 : 업로드와 연계해서 사용할 경우 알아서 업로드된 파일을 첨부해서 메일을 보냅니다.

언제나 '공대여자는 예쁘다'는 마음가짐이 있어야 사용하실 수 있습니다.
==========================*/
function mail_fsend($tos,$subject,$message='',$addtion_header='',$files=array()){
//첨부파일 가능용
/*
추천 해더설정
$addtion_header['content_type']  ='text/html';
$addtion_header['char_set']='UTF-8'; or $addtion_header['char_set']='EUC-KR';
*/
// $files: 는 서버내의 파일을 지목할 때 사용
    //============================================== 기초 설정
    $boundary = "----=b".md5(uniqid(time()));
    
    $content_type= $addtion_header['content_type'];    //기본내용형식 : 일반 text
    if(empty($content_type)) $content_type='text/plain';            //기본문자셋 : utf-8    
    $char_set = $addtion_header['char_set'];
    if(empty($char_set)) $char_set='UTF-8';            //기본문자셋 : utf-8
    //=====================================================to 설정
    if(is_string($tos)){
        $to = $tos;
    }else if(is_array($tos)){
        $to = implode(', ',$tos);
    }
    //=====================================================subject 설정
    if(empty($subject)){
    $subject = 'No title '.date('Y-m-d H:i:s');
    }
    //$subject = '=?EUC-KR?B?'.base64_encode($subject).'?=';
    $subject = '=?'.$char_set.'?B?'.base64_encode($subject).'?=';     
    //=====================================================해더 설정
    $headers=array();
$headers['mime_version']='MIME-Version: 1.0';
//$headers['content_type']="Content-type: multipart/alternative; boundary=\"{$boundary}\"";
$headers['content_type']="Content-type: multipart/mixed; boundary=\"{$boundary}\"";


    if(!empty($addtion_header['from'])){        $headers[]= "From: ".$addtion_header['from'];    }
    else{        $headers[]= "From: webmaster@{$_SERVER['SERVER_NAME';]}";    }    
    if(!empty($addtion_header['cc'])){        $headers[]= "cc: ".$addtion_header['cc'];    }
    if(!empty($addtion_header['bcc'])){        $headers[]= "Bcc: ".$addtion_header['bcc'];    }            

    if(!empty($headers)){        $header = implode("\r\n",$headers)."\r\n";    }
    else{        $header ='';    }
    //======================================================== 메세지 인코딩
    $msg_content_type = "Content-type: {$content_type}; charset={$char_set}";
    
    $msg = '';
    $msg .= mail_fsend_enc_msg($boundary,$message,$msg_content_type); //본문 메세지 처리
    //======================================================== 첨부파일 인코딩
    if(!is_array($files)){$files=array($files);}//강제로 배열로 만든다.
    for($i =0,$m=count($files);$i<$m;$i++){
        $msg .= mail_fsend_enc_file($boundary,$files[$i]); //첨부파일 처리
    }
    //======================================================== 업로드 되는 첨부파일 인코딩    
    if(!empty($_FILES)){
        foreach($_FILES as $key=> $value){            $t = $key; break;        }
        $t_files = $_FILES[$t]['tmp_name'];
        $t_filenames = $_FILES[$t]['name'];
        $t_error = $_FILES[$t]['error'];
        if(!is_array($t_files)){$t_files=array($t_files);}
        if(!is_array($t_filenames)){$t_filenames=array($t_filenames);}
        if(!is_array($t_error)){$t_error=array($t_error);}
        for($i =0,$m=count($t_files);$i<$m;$i++){
            if($t_error[$i]==0){
                $msg .= mail_fsend_enc_file($boundary,$t_files[$i],$t_filenames[$i]); //첨부파일 처리
            }
        }    
    }
    //========================================================= 메세지 닫기
    $msg .='--'.$boundary."--";
    //===================================================== 메일 보내기
    //===================================================== 릴레이션 설정이 필요한 경우는 알아서...
    $result = mail ($to,$subject,$msg,$header);
    return $result;    
}
function mail_fsend_enc_msg($boundary,$msg='',$content_type='Content-type: text/plain; charset=utf-8'){
//본문문자열 인코딩
    $re_str = '';
    $re_str = '--'.$boundary."\r\n"; //바운드리 설정
    $re_str .= $content_type."\r\n";
    $re_str .= 'Content-Transfer-Encoding: base64'."\r\n"."\r\n";    
    // RFC 2045 에 맞게 $data를 형식화
    $new_msg = chunk_split(base64_encode($msg));
    $re_str .=$new_msg."\r\n";
    return $re_str;
}
function mail_fsend_enc_file($boundary,$file,$filename=''){
//첨부파일 인코딩
    $content_type = 'Content-Type: application/octet-stream; charset=UTF8';
    $re_str = '';
    $re_str = '--'.$boundary."\r\n"; //바운드리 설정
    $re_str .= $content_type."\r\n";
    $re_str .= 'Content-Transfer-Encoding: base64'."\r\n";    
    if(strlen($filename)==0){        $filename = basename($file);    }
    $re_str .= "Content-Disposition: attachment; filename=\"".'=?UTF-8?B?'.base64_encode($filename).'?='."\""."\r\n"."\r\n";        
    
    // RFC 2045 에 맞게 $data를 형식화    
    $fp = @fopen($file, "r");
    if($fp) {    $msg = fread($fp, filesize($file));    fclose($fp);    }    
    
    $new_msg = chunk_split(base64_encode($msg));
    $re_str .=$new_msg."\r\n";
    
    return $re_str;
}
//-----------------------------------------------------------------------
함수 사용법

---------------------=---------------------------
솔찍히 이건 함수를 사용하시라는게 아니라 참고하시라고 올려놓는 겁니다.


메일의 경우 여러 규격이 있지만 그중에서 가장 많이 사용되는 규격중에서
첨부파일을 처리하는 방법은 RFC 2045 입니다.
그 규격은 multipart/mixed 와 boundary , base64_encode 가 요점입니다.

==========================================
멀티파트로 보낼 경우 기본적 구조

  # 해더
Content-type: multipart/mixed; boundary="123456"  를 선언

  # 본문

--123456 (\r\n 으로 줄바꿈)
Content-type: text/plain; charset=utf-8(\r\n)
Content-Transfer-Encoding: base64(\r\n)
(\r\n)
 chunk_split(base64_encode(메세지));(\r\n)
--123456 (\r\n 으로 줄바꿈)
Content-type: application/octet-stream; charset=utf-8(\r\n)
Content-Transfer-Encoding: base64(\r\n)
Content-Disposition: attachment; filename=파일이름(\r\n)
(\r\n)
 chunk_split(base64_encode(메일내용));(\r\n)
--123456--


-> 설명
#해더에서 Content-type 를  multipart/mixed 로 선언
바운더리로 사용할 123456 를 선언

#본문에서
'--123456' 으로 바운더리를 적어서 그부분이 하나의 파트라는 것을 표시
바로밑에 content-type 등을 적고 \r\n으로 줄바꿈
본메세지와는 \r\n으로 한줄이 더 생기도록 함
본메세지는  chunk_split(base64_encode($msg));(\r\n) 로 삽입
(chunk_split : RFC 2045형식에 맞도록 문자열을 줄바꿈 해줍니다.)
(base64_encode : 메일의 기본은 64 인코딩입니다.)
이로 일반 메세지 부분은 끝

또다시 '--123456' 으로 바운더리를 적어서 그부분이 하나의 파트라는 것을 표시
파일을 첨부할 경우
Content-type: application/octet-stream; charset=utf-8(\r\n)
Content-Transfer-Encoding: base64(\r\n)
Content-Disposition: attachment; filename=파일이름(\r\n)
(\r\n)
라고 삽입
본메세지는 파일안의 내용으로
chunk_split(base64_encode(파일안의 내용));(\r\n) 를 삽입

마지막으로
'--123456--' 으로 끝이라고 표시

====================-=============
설명이 이상한것 같은데
어쨌든 중요한건 해더에 선언하는 content-type과
부분을 나누는 boundary 입니다.

이것만 기억하면 간단하게 첨부파일 메일 보내기는 성공하실 수 있습니다.
반응형