ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 파이썬으로 이메일(gmail) 보내기..
    Python/이것저것 파이썬 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

     

    반응형
Designed by Tistory.