본문 바로가기
etc

SMTP 로 html 메일보내기 + 이미지

by reo.l 2021. 8. 30.

django에서 제공하는 email 기능을 사용하여 html에 이미지 첨부하여 메일을 보냈으나 gmail에서는 적용이 잘 됐는데 naver에서는 자체 보안이 돼있는지 이미지가 보이지 않았다. 그래서 smtp 프로토콜을 사용하여 메일을 보내기로 했다.

 

SMTP 란?

간이 전자 우편 전송 프로토콜(Simple Mail Transfer Protocol, SMTP)은 인터넷에서 이메일을 보내기 위해 이용되는 프로토콜이다. 사용하는 TCP 포트번호는 25번이다. 상대 서버를 지시하기 위해서 DNS의 MX 레코드가 사용된다. RFC2821에 따라 규정되어 있다. 메일 서버 간의 송수신뿐만 아니라, 메일 클라이언트에서 메일 서버로 메일을 보낼 때에도 사용되는 경우가 많다.

SMTP는 텍스트 기반의 프로토콜로서 요구/응답 메시지뿐 아니라 모든 문자가 7bit ASCII로 되어있어야 한다고 규정되어 있다. 이 때문에 문자 표현에 8비트 이상의 코드를 사용하는 언어나 첨부파일과 자주 사용되는 각종 바이너리는 마임(MIME)이라고 불리는 방식으로 7비트로 변환되어 전달된다.

SMTP는 메시지를 생성하는 방법을 규정하지 않는다. 메시지 생성을 위하여 로컬 편집이나 단순한 전자 우편 응용이 사용된다. 메시지가 생성되면 호출된 SMTP가 메시지를 받고 TCP를 이용하여 다른 호스트의 SMTP에게 전달한다.

( 참고 : https://ko.wikipedia.org/wiki/%EA%B0%84%EC%9D%B4_%EC%9A%B0%ED%8E%B8_%EC%A0%84%EC%86%A1_%ED%94%84%EB%A1%9C%ED%86%A0%EC%BD%9C )

 

먼저 smtplib를 import 하여 주고 server name, id, password, port를 설정해준다. 

 

import smtplib

smtp_info = dict(
                   {"smtp_server" : "smtp.gmail.com",
                    "smtp_user_id" : "id" ,
                    "smtp_user_pw" : "password" ,
                    "smtp_port" : 587}
                  )

 

gmail 서버를 사용하였는데 password 같은 경우는 application password를 구글 아이디 설정 탭에서 직접 받아야 한다. 

이제 msg 객체를 return 하는 함수를 만들어 주겠다. 여기서는 msg에 여러 가지 형식(html, audio, img 등)의  정보들을 알맞게 결합시켜줄 것이다. 

 

msg_dict = {
            'image' : {'maintype' : 'image', 'subtype' :'jpg', 'filename' :'/home/ubuntu/test.jpg'}, # 이미지 첨부파일
        }

def make_multimsg(msg_dict,username):
        multi = MIMEMultipart(_subtype='mixed')
        image_path = '/home/ubuntu/test.jpg'
        image_name = Path(image_path).name

        html_message = f"""
        <!doctype html>
            <html lang=en>
                <head>
                    <meta charset=utf-8>
                    <title>Some title.</title>
                </head>
                <body>
                    <h3>"회원 가입이 완료되었습니다."</h1>
                    <p>
                    {username}님 가입해 주셔서 감사합니다.<br>
                    <img style="width: 800px;" src='cid:{image_name}'/>
                    </p>
                </body>
            </html>
        """
        html_body = MIMEText(html_message, 'html')
        multi.attach(html_body)

        for key, value in msg_dict.items():
            with open(value['filename'], 'rb') as fp:
                msg = MIMEImage(fp.read(), _subtype=value['subtype'],Name='서비스 소개서')
            msg.add_header('Content-ID', f"<{image_name}>")
            multi.attach(msg)
        
        return multi

 

msg_dict에는 html, audio 등 여러 가지 형식을 설정하여 줄 수 있다. 여기서는 img 파일만 첨부할 것이다. msg_dict를 순회하며 msg에 attach 해주고 그 attach 된 파일들은 html 문서의 cid 값에 따라서 첨부된다. Content_ID와 cid 부분을 일치시켜주어야 html에 첨부되니 주의해야 한다.

 

이렇게 msg 객체를 만들어주면 서버를 열고 보내주기만 하면 된다.

 

smtp_info = dict(
                 {"smtp_server" : "smtp.gmail.com",
                  "smtp_user_id" : "id" ,
                  "smtp_user_pw" : "appication password" ,
                  "smtp_port" : 587}
                )

msg_dict = {
    'image' : {'maintype' : 'image', 'subtype' :'jpg', 'filename' :'/home/ubuntu/test.jpg'}, # 이미지 첨부파일
}

title = "회원 가입이 완료되었습니다."
content = "안녕하세요"
sender = "sender@email.com"
receiver =  email

# 메일 내용
msg = MIMEText(_text = content, _charset = "utf-8") 

# 첨부파일 추가
multi = make_multimsg(msg_dict,receiver)
multi['subject'] = title  
multi['from'] = sender  
multi['to'] = receiver     
multi.attach(msg)

with smtplib.SMTP(smtp_info["smtp_server"], smtp_info["smtp_port"]) as server:
    # TLS 보안 연결
    server.starttls() 
    # 로그인
    server.login(smtp_info["smtp_user_id"], smtp_info["smtp_user_pw"])
    # 로그인 된 서버에 이메일 전송
    response = server.sendmail(multi['from'], multi['to'], multi.as_string()) # 메시지를 보낼때는 .as_string() 메소드를 사용해서 문자열로 바꿔줍니다.

 

naver로 접속해서 확인해 보면 이메일이 잘 가는 것을 확인할 수 있다.

 

 

 

 

 

댓글