PHP

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

raim-2 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으로 첨부한 이미지를 본문에서 이미지 태그로 볼 수 있다!

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

 

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