Python/이것저것 파이썬

파이썬으로 이메일(gmail) 보내기..

컴닥 2021. 11. 14. 20:03
반응형

페이스북 코딩 모임에 올라온 글.

 

이름, 이메일, 쿠폰 번호가 들어있는
다음 CSV 파일을 이용해
이메일을 보내는 코드를 작성하십시오.
단. 파이써닉하게~!

 

재미있을 것 같아서...
한 번 작성해 보았습니다.

 

list.csv

1,김씨,kim@test_email.com,1111
2,이씨,lee@test_email.com,2222
3,정씨,jung@test_email.com,3333

 

1. 답답한 스타일입니다. 

딕셔너리나 리스트에 CSV파일의 데이터를 넣은 뒤 메일을 보냅니다.

* gmail을 이용하려면, 구글 계정의 보안 수준이 낮은 앱 허용을 체크해야 합니다.
* 코드 내의 비밀번호 유출 주의~!

from csv import reader
from email.mime.text import MIMEText
from smtplib import SMTP

send_from = 'test@gmail.com'
password = 'passw0rd'

mail_dict = {}

f = open('list.csv', 'r', encoding='utf-8')
r = reader(f)
for _, name, send_to, code in r:
    mail_dict[name] = (send_to, code)
f.close()

smtp = SMTP('smtp.gmail.com', 587)
# smtp.set_debuglevel(2)
smtp.ehlo()
smtp.starttls()
smtp.login(send_from, password)
for name, (send_to, code) in mail_dict.items():
    msg = MIMEText(f'할인쿠폰 코드는 {code} 입니다.')
    msg['Subject'] = '할인쿠폰 코드'
    msg['To'] = send_to
    smtp.sendmail(send_from, send_to, msg.as_string())
    print(f'Sent to {send_to}')
smtp.quit()

 

2. 평범한 스타일입니다. 

with ~ as ~ 를 사용했습니다.
2줄이 줄고, 들여쓰기가 되었을 뿐인데 읽기도 편해집니다. 

from csv import reader
from email.mime.text import MIMEText
from smtplib import SMTP

send_from = 'test@gmail.com'
password = 'passw0rd'

mail_dict = {}

with open('list.csv', 'r', encoding='utf-8') as f:
    r = reader(f)
    for _, name, send_to, code in r:
        mail_dict[name] = (send_to, code)

with SMTP('smtp.gmail.com', 587) as smtp:
    # smtp.set_debuglevel(2)
    smtp.ehlo()
    smtp.starttls()
    smtp.login(send_from, password)

    for name, (send_to, code) in mail_dict.items():
        msg = MIMEText(f'할인쿠폰 코드는 {code} 입니다.')
        msg['Subject'] = '할인쿠폰 코드'
        msg['To'] = send_to
        smtp.sendmail(send_from, send_to, msg.as_string())
        print(f'Sent to {send_to}')

파이썬의 with as문은 close를 자동으로 해주는 구문입니다. 
(컨텍스트 매니저라고도 합니다.)
파일이나 데이터베이스 접속 종료 시 하나 하나 클로즈하지 않아도 되어 편리합니다.

파이썬에서는 클래스를 만들 때 미리 __exit__ 메서드를 만들어 두면
종료 시 그 메서드를 자동으로 실행합니다.
(이런 특수한 메서드들을 매직 메서드라고 합니다.)
여기서는 라이브러리 개발자들이 미리 만들어 둔 걸 사용한 것입니다. 

open은 close로 종료되고, SMTP는 quit로 종료됩니다. 
파이썬에서 표준화된 규약( __exit__ 메서드를 이용하라. )에 따라 코딩하면
with as 만 기억하면 됩니다. 표준화가 주는 장점이군요. 

SMTP.__exit__

 

3. 제너레이터를 이용하면 더 좋지 않을까요?

from csv import reader
from email.mime.text import MIMEText
from smtplib import SMTP

send_from = 'test@gmail.com'
password = 'passw0rd'


def read_csv():
    with open('list.csv', 'r', encoding='utf-8') as f:
        r = reader(f)
        for _, name, send_to, code in r:
            yield name, send_to, code


def send_mail():
    with SMTP('smtp.gmail.com', 587) as smtp:
        # smtp.set_debuglevel(2)
        smtp.ehlo()
        smtp.starttls()
        smtp.login(send_from, password)

        for name, send_to, code in read_csv():
            msg = MIMEText(f'할인쿠폰 코드는 {code} 입니다.')
            msg['Subject'] = '할인쿠폰 코드'
            msg['To'] = send_to
            smtp.sendmail(send_from, send_to, msg.as_string())
            print(f'Sent to {send_to}')


send_mail()

파이썬의 yield는 함수가 끝나지 않은 상태에서 (실행 중간에) 값을 함수 외부로 전달해 줄 수 있습니다. 
딕셔너리, 리스트 등 임시 저장 공간을 사용하지 않기 때문에 메모리를 절약할 수 있습니다. 
오랜 시간이 걸리는 일을 중간중간 끊어서 갈 때 사용해도 좋습니다. 

이런 (끝나지 않은 상태에서 값이 외부로 전달 되는) 함수를 제너레이터라고 합니다. 
함수형 프로그래밍에서는 자주 접하는 개념이지요. 

파이썬은 간단하게 쓸 때는 스크립트로...
진지하게(?) 쓸 때는 객체지향으로...
특이하게(?) 접근할 땐 함수형으로 쓸 수도 있습니다.

파이썬은 재미있습니다. 

 

4. yield from을 쓰면 더 깔끔합니다.

* yield from은 파이썬 3.3에서 도입되었습니다. 

from csv import reader
from email.mime.text import MIMEText
from smtplib import SMTP

send_from = 'test@gmail.com'
password = 'passw0rd'


def read_csv():
    with open('list.csv', 'r', encoding='utf-8') as f:
        yield from reader(f)


def send_mail():
    with SMTP('smtp.gmail.com', 587) as smtp:
        # smtp.set_debuglevel(2)
        smtp.ehlo()
        smtp.starttls()
        smtp.login(send_from, password)

        for _, name, send_to, code in read_csv():
            msg = MIMEText(f'할인쿠폰 코드는 {code} 입니다.')
            msg['Subject'] = '할인쿠폰 코드'
            msg['To'] = send_to
            smtp.sendmail(send_from, send_to, msg.as_string())
            print(f'Sent to {send_to}')


send_mail()

yield from [반복 가능한 객체, 이터레이터, 제너레이터]

yield from을 사용하면
for 문 없이 반복 가능한 객체의 원소 하나 하나씩을
함수의 외부로 보내줄 수 있습니다. 

(3번째 코드 중)
for _, name, send_to, code in r: 에서
r 이 반복적인 객체였고,
r = reader(f)에서
reader(f)이 반복의 근원이었음을 알 수 있습니다. 

깔끔하게 yield from reader(f) 을 사용하여 한 줄씩 외부로 바로 쏴줍니다. 

 

https://dojang.io/mod/page/view.php?id=2414 

 

파이썬 코딩 도장: 40.3 yield from으로 값을 여러 번 바깥으로 전달하기

지금까지 yield로 값을 한 번씩 바깥으로 전달했습니다. 그래서 값을 여러 번 바깥으로 전달할 때는 for 또는 while 반복문으로 반복하면서 yield를 사용했습니다. 다음은 리스트의 1, 2, 3을 바깥으로

dojang.io

 

반응형