ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • php mail() 첨부파일 메일 보내기 2탄_이미지로 처리
    PHP 2023. 5. 30. 16:15
    반응형

    php mail() 첨부파일 메일 보내기 2탄_이미지로 처리하기 

     

    1탄에서는 form 형식 내 type이 file인 input에서 이미지 선택시 미리보기가 가능하도록

    fileReader api와 file 속성을 이용해 js로 처리했다.

     

    👉 이번에 구현하려 했던 부분 

    1. 선택한 파일의 미리보기 이미지 보여주기
    2. php mail() 사용해 첨부파일 메일 보내기 + 메일 본문에서 이미지 미리보기
      👉 얘는 됐다 안됐다 반복중.....🤦‍♀️(해결 이미지로 처리하는 것만)

     

    오늘은 구현하려 했던 부분 중 2번 정리!

    *내가 보기 위해 정리한 것임. 틀리거나 코드가 더러울 수 있음 주의*

     


    ✔️ 첨부한 이미지, 메일 본문에 이미지 태그로 처리하기

     

    정말... 이 부분 처리하면서 빡친 부분이 한두개가 아니다.

    물론 내가 아직 능숙하게 해낼 정도의 실력이 아닌 게 문제겠지만....하여튼!

     

    내가 하다가 빡쳤던 부분을 정리하자면 

    1. 첨부파일 형태로 파일을 받을 수 있음 👉얘가 메일 왔다 안왔다 반복...(아직 미해결)
    2. 이미지 태그 형태로 본문에 포함할 수 있음(마우스 우클릭으로 저장 가능) (얘는 가능)

     

    👉첫 번째 이미지가 1번 첨부파일 형태로 전달받은 거고, 두 번째 이미지가 이미지 태그 형태로 포함한 것

    솔직히 맨 처음 생각한 부분은 2번 형태로 생각했었는데, 이것저것 참고해서 하다보니 1번이 되길래 오! 얘도 괜찮군이라 생각했다.그런데, 분명 되는구나 다 체크하고 깃허브에 올리고 다음날 체크하면 또 안되고 ....또 되고 난리를 치는 거...🤦‍♀️

     

    우선 오늘은 2번 형태로 전달하는 방법 정리하고 1번 에러 해결하면 1번 형태로도 정리해야지😥

     

     

     

     

    1) mail.php 파일을 만든다.

    2) post 방식을 사용했으므로, $_POST, 파일 타입을 사용했으니 $_FILES 해당 전역변수를 사용해서 사용자로부터 받은 데이터를 변수에 저장한다. 데이터를 부러올 때는 input의 name 속성의 값을 이용한다.

     

    form 전송방식 -  GET, POST 가 있다.
    GET으로 전송된 값은 $_GET으로 받고, 
    POST로 전송된 값은 $_POST로 받는다.

     

    <?php
    
     $name_01=$_POST['name'];
     $mail_02=$_POST['email'];
     $phone_03=$_POST['tel'];
     $type_04=$_POST['type'];
     $msg_05=$_POST['message'];
     $file_06=$_FILES['file']; //전달될 때 이진형태로 전달
     $agree_07=$_POST['agree'];
    
     $file_name=$_FILES['file']['name'];
     $file_size=$_FILES['file']['size'];
     $file_type=$_FILES['file']['type'];
     $file_tmp=$_FILES['file']['tmp_name']; //임시명 - 임시경로(서버 저장전)

     

     

    * 유효성 검사는 별도로 하지 않았다. 필요하면 나중에 참고해서 넣어야지

    3)  파일 타입이 없을 때는 application/octet-stream로 처리해준다.

     

    application/octet-stream : MIME type 중 하나로 8bit의 이진형식으로 처리한다는 뜻 (특별히 표현할 형태가 없을 때 사용한다.)
    참고 : https://velog.io/@kim_sunnnny/what-is-applicationoctet-stream

    MIME type: MIME은 Multipurpose Internet Mail Extensions의 약자로 이메일과 함께 첨부할 파일을 텍스트 문자로 변환해서 전달하기 위해 개발
    👉 현재는 웹을 통해 여러 형태의 파일을 전달할 때 쓰인다.


    참고 : 
    https://babycoder05.tistory.com/entry/%EC%9D%B8%EC%BD%94%EB%94%A9-Base64-MIME-Type

     

    // 파일 첨부가 없는 경우 기본 MIME 유형을 설정
    if ($file_type == "") {
        $file_type = 'application/octet-stream';
    };

     

     

    4) 파일 열고, 읽고, 닫기

    파일을 열때는 fopen(), 읽을 때는 fread(), 닫기는 fclose()를 사용한다.

    fopen()의 2번째 인수는 "r"은 읽기 전용을 의미한다.

    fread()로 파일 내용을 읽어, 해당 내용을 $file 변수에 저장한다.

     

    base64_encode()함수를 사용해 base64로 인코딩하고,

    chunk_split() 을 사용해 인코딩된 파일을 청크로 분할한다.

     

    base64_encode() : 이진데이터를 base64로 인코딩 해주는 함수

    👉 왜 사용하는가?
    이진 데이터의 경우 일부 플랫폼이나 프로토콜에서 제대로 처리가 되지 않을 수 있기 때문에, base64로 인코딩 시 문자 인코딩에 영향을 받지 않는 공통 ASCII(아스키) 영
    역의 문자들로만 이루어진 일련의 문자열 형태로 변환되어 데이터의 호환성이 향상되기 때문이다.

    참고 : https://blue-boy.tistory.com/227https://babycoder05.tistory.com/entry/%EC%9D%B8%EC%BD%94%EB%94%A9-Base64-MIME-Type

    chunk : 하나의 큰 덩어리 
    chunk_split() : 문자열을 더 작은 덩어리로 분할해주는 함수

    👉 왜 사용하는가?
    데이터를 지정된 길이마다 분할해 구분 기호를 삽입하며, 청크된 문자열을 반환한다. 데이터를 지정된 길이마다 잘라서 처리하게 되면, 데이터를 한 번에 보내는 것보다 성능면에서 더 유리하다는 장점이 있다

     

    //별도로 data 파일에 이미지 저장 안됨
    $filename = basename($file_name);
    $fp = fopen($file_tmp, "r"); // 임시 경로($file_tmp)에서 해당 파일을 열어준다.
    $file = fread($fp, $file_size);
    fclose($fp);
    
    $attach = chunk_split(base64_encode($file));
    $image_tag = "<img src=\"data:$file_type;base64,$attach\" alt=\"첨부파일 이미지\" style=\"width: 100%;\">";

     

    5) 메일에 들어갈 변수 지정하기

    $boundary 값은 md5(uniqid(microtime()));

    현재 시간을 기반으로 고유한 식별자 생성

    👉 입력 데이터를 고정 길이의 해시 값으로 변환한 값으로 식별(각각 고유한 값을 가짐)을 위해 사용한다.

     

    $boundary는 멀티파트 메일 구성 시 여러 부분으로 구성되어 있는 메일의 각 부분을 $boundary 값을 이용해 구분한다.

    👉멀티파트 메일 구성 시에 필수 요소임 - 없으면 안써도 된다. 이번엔 2번 구현이라 뺐음!

     

    "" 큰따옴표 내 문자열 정의시 변수(변수의값) 포함한 문자열 표현 가능
    "Hello, $name!"  - $name은 해당 변수의 값으로 대체
    큰따옴표 안에서 큰따옴표를 문자열로 사용하고 싶으면 앞에 \를 붙인다.
    "<img src=\"./data/$file_path\">"

    '' 작은따옴표 내 문자열 정의시 변수(문자열) 포함한 문자열 그대로 표시
    'Hello, $name!' - $name은 그대로 $name으로 표시
    변수의 값으로 처리하려면 .연산자로 연결 'Hello,'.$name.'!'

     

     $to='aaa@naver.com'; //master mail
     $subject='사이트에서 관리자에게 보낸 메일';
     $msg="<br>보낸사람: $name_01<br>".
         "보낸사람 전화번호: $phone_03<br>".
         "문의유형: $type_04<br>".
         "내용: $msg_05<br>".
         "개인정보 수집 및 이용동의: $agree_07<br>";
    
    $attach_msg="<hr>첨부파일 이름: {$file_name}<br>".
            "첨부파일 크기: {$file_size}<br>".
            "첨부파일 타입: {$file_type}<br>".
            "첨부파일 이미지:";
    
    //$boundary = md5(uniqid(microtime()));

     

    6) 조건문을 사용해 파일이 선택된 상태와 선택되지 않은 상태로 나눠 메일을 구성한다.

     

    $header는 메일 헤더를 구성하는 데 사용되며, 

    메일 속성과 포맷을 정의해 수신자에게 메일을 어떻게 표시할 지 알려주는 부분이다. 

    • MIME-Version : 메일에서 다양한 데이터를 표현하고 전송하기 위한 규약. 일반적으로 1.0 사용
    • Content-Type : 메일 본문의 콘텐츠 타입을 지정.
      "text/plain"은 일반 텍스트 메일을 나타내고, "text/html"은 HTML 형식의 메일을 나타낸다.
    • Content-Transfer-Encoding: 메일 본문의 인코딩 방식을 지정
      일반적으로 "8bit"이나 "base64"를 사용한다.
    • 그 외에 발신자, 메일의 제목, 수신자, 참조자, 숨은 참조자 등의 정보를 추가할 수 있다.

     

    * 첨부파일을 포함하는 경우 Content-Type은 multipart로 지정, boundary도 지정해준다.

    👉 $headers .= "Content-Type: multipart/mixed; boundary=\"$boundary\"\r\n";

    얘도 2번 형태로(본문 내 미리보기 이미지) 구현하는 거라 사용하진 않았다.

     

    대신 메일 본문 내에 이미지 태그를 사용해 구현할 거라 Content-Type은 html을 사용했고, 

    $image_tag 변수를 본문 안에 넣어줬다.

    $image_tag = "<img src=\"data:$file_type;base64,$attach\" alt=\"첨부파일 이미지\" style=\"width: 100%;\">";

     

    7) mail() 함수를 사용한다.

    mail(수신인, 메일제목, 본문내용, 헤더)

     

    if ($file_tmp == "") {
       $headers = "MIME-Version: 1.0\r\n";
       $headers .= "Content-Type: text/html; charset=UTF-8\r\n";
       $headers .= "Content-Transfer-Encoding: 8bit\r\n\r\n";
       $headers .= "보낸사람 메일주소: $mail_02" . "\r\n";
    
       $bodytext = $msg;
    } else {
       $headers = "MIME-Version: 1.0\r\n";
       $headers .= "Content-Type: text/html;\r\n";
       $headers .= "Content-Transfer-Encoding: 8bit\r\n\r\n";
       $headers .= "보낸사람 메일주소: $mail_02" . "\r\n";
    
       $bodytext .= $msg . "\r\n\r\n";
       $bodytext .= $attach_msg . "\r\n\r\n";
       $bodytext .= "<div class=\"attach\" style=\"width:30%; height: auto; margin-top: 30px;\">$image_tag</div>" . "\r\n";
    };
    
    mail($to, $subject, $bodytext, $headers);    
    
    echo "<script>
            alert('성공적으로 메일이 전송되었습니다.');
            //history.go(-1);
            location.href='./sub6_3.html' ;
    </script>
    ";
    ?>

     

    이렇게 하면, input으로 첨부한 이미지를 본문에서 이미지 태그로 볼 수 있다!

    이미지 태그라 마우스 우클릭하면 다운도 가능하다. 대신 첨부파일 형태가 아닌게 ... 🤔

     

    다음엔 첨부파일 형태로 받기 작성해야지...해결하고

    댓글

Designed by Tistory.