Ứng dụng Python

Sử dụng python để gửi mail

Đăng bởi - Ngày 24-05-2018

Chào mọi người, chủ đề hôm nay mình viết về cách gửi mail trong python, đây cũng là một đề tài không mới nhưng rất thiết thực. Hy vọng sẽ giúp ích cho mọi người.

Yêu cầu của bài này sẽ là: chúng ta sẽ có danh sách mail để gửi cho khách hàng, mỗi danh sách có tên và địa chỉ email. Mỗi một mail gửi ra sẽ có dòng chào khách hàng là: Chào [tên khách hàng] trong nội dung mail.

Danh sách khách hàng bạn có thể lưu ở một file txt cho dễ sử dụng hơn là trong database, trừ khi bạn muốn gán cờ xem khách hàng nào đã nhận mail rồi. Và template mail chúng ta cũng sẽ lưu trong một file txt

Về cơ bản thì bạn có thể gửi mail đơn giản không cần tiêu đề với module smtplib của python, nhưng khi bạn gửi mail quảng cáo cho khách hàng, bạn sẽ cần thêm nhiều thông tin hơn như tiêu đề mail, tên khách hàng, hoặc các file đính kèm theo mail

Để giải quyết vấn đề trên bạn cần phải kết hợp email package với smtplib lại để gửi email hoàn chỉnh.

Đây là các bước gửi mail cơ bản để gửi mail trong python

  1. Cài đặt SMTP Server và đăng nhập vào account của bạn
  2. Tạo một object Mimemultipart và đưa vào các thông tin cần thiết như là: From, To, Subject
  3. Thêm vào nội dung mail
  4. Gửi mail thông qua SMTP server

Bây giờ chúng ta sẽ tạo một file listmails.txt chứa danh sách khách hàng với nội dung như sau

hoc python|hotro.hocpython@gmail.com
another mail|test.anothermail1239918@gmail.com

Mỗi dòng là một khách hàng với định dạng là name|email. Các bạn có thể viết hoa hoặc thường cho email, nhưng khi gửi ra chúng ta sẽ chuyển mail thành viết thường toàn bộ

Tiếp đến là tạo một file templatemail.txt với nội dung như sau

Chào ${CUSTOMER_NAME},

Đây là mail được gửi từ chương trình mail của python.

Trong nội dung templatemail.txt bạn sẽ thấy ${CUSTOMER_NAME}, đây là template stringscủa python. Lưu ý rằng bạn không bắt buộc phải sử dụng đúng variable CUSTOMER_NAME mà thay bằng bất cứ chuỗi nào mà bạn muốn. Chúng ta sẽ gán tên của customer và CUSTOMER_NAME và gửi đi trong mail

Ok, chúng ta sẽ bắt đầu viết code cho chương trình. Việc cần làm đầu tiên là chúng ta sẽ lấy tên và mail của khách hàng từ file listmails.txt. Bạn hãy tạo file app.py, sau đó tạo function get_customer_information như sau

def get_customer_information(filename): #1
    customer = [] #2

    with open(filename, mode='r', encoding='utf-8') as line: #3
        for info in line.read().splitlines(): #4
            tmp_info = info.split('|') #5
            customer.append({'name': tmp_info[0], 'email': tmp_info[1]}) #6

    return customer #7
  1. Function get_customer_information sẽ nhận vào một tham số là file chứa thông tin khách hàng. Trong trường hợp bài viết này sẽ là listmails.txt
  2. Ta sẽ tạo một list customer để lưu email và name của customer
  3. Đây là cách python đọc một file với mode là read và encoding với utf-8
  4. Ta sẽ lấy tất cả nội dung trong file thông tin khách hàng thông qua vòng lặp
  5. Mỗi một dòng thông tin được format theo dạng name|email, vì vậy chúng ta sẽ tách name và email bằng method split với ký tự |
  6. Ta sẽ append list customer với một dict có 2 phần tử là name và email
  7. Cuối cùng là trả về một list với tất cả thông tin customer lấy được trong file

Chạy thử app.py và kết quả trả về như sau

/var/projects/flask/flask-projects/pyserver/bin/python3 /var/projects/python/learningpython3/sendmailsmtp/app.py
[{'name': 'hoc python', 'email': 'hotro.hocpython@gmail.com'}, {'name': 'another mail', 'email': 'test.anothermail1239918@gmail.com'}]

Process finished with exit code 0

Tiếp theo, chúng ta cần viết một function khác để lấy template mail

from string import Template #1

def get_template(filename): #2
    with open(filename, 'r', encoding='utf-8') as template_content:
        tmp_content = template_content.read()
        return Template(tmp_content) #3
  1. Để sử dụng template strings, ta cần import class Template từ module string
  2. Function get_template nhận vào một tham số là file name
  3. Sau khi lấy nội dung mail, ta sẽ convert sang template object và trả về

Để gửi mail, chúng ta sẽ sử dụng SMTP (Simple Mail Transfer Protocol). Đây là built-in function của python.

import smtplib #1

smtp_info = {
    'SMTP_ENCRYPT': 'tls',
    'SMTP_ADDRESS': 'smtp.gmail.com',
    'SMTP_PORT': 587,
    'MAIL_LOGIN': '',
    'MAIL_PASSWORD': '',
} #2

if smtp_info.get('SMPT_ENCRYPT', "tls"): #3
    s = smtplib.SMTP(host=smtp_info.get('SMTP_ADDRESS'), port=smtp_info.get('SMTP_PORT')) #4.1
    s.starttls()
else:
    s = smtplib.SMTP_SSL(host=smtp_info.get('SMTP_ENCRYPT'), port=smtp_info.get('SMTP_PORT')) #4.2
    s.ehlo()

s.login(smtp_info.get('MAIL_LOGIN'), smtp_info.get('MAIL_PASSWORD')) #5
  1. Để dùng smtp của python bạn cần import smtplib
  2. Tạo một dict smtp_info dùng để chứ các thông tin để login vào mail server. Ở đây mình sẽ set giá trị SMTP Server là của gmail. Bạn có thể đổi thành server của bạn để test. MAIL_PASSWORD bạn hãy dùng app password để đăng nhập
  3. Vì mỗi smtp encrypt có cách thức kết nối khác nhau nên chúng ta chia ra hai trường hợp
  4. Với 4.1 thì là kết nối với tls chúng ta dùng smtp để kết nối với smtp server, và ngược lại nếu là kết nối với ssl, thì như 4.2 ta sẽ dùng SMTP_SSL.
  5. Sau khi kết nối với smtp server, chúng ta tiến hành đăng nhập

Tất cả nguyên liệu đã sẵn sàng, bây giờ chúng ta sẽ đặt tất cả lại với nhau, file app.py sẽ như thế này

import smtplib
import logging
from string import Template
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText


def get_customer_information(filename):
    customer = []

    with open(filename, mode='r', encoding='utf-8') as line:
        for info in line.read().splitlines():
            tmp_info = info.split('|')
            customer.append({'name': tmp_info[0], 'email': tmp_info[1]})

    return customer


def get_template(filename):
    with open(filename, 'r', encoding='utf-8') as template_content:
        tmp_content = template_content.read()
        return Template(tmp_content)


if __name__ == "__main__":
    customers = get_customer_information('listmails.txt') #1
    message_template = get_template('templatemail.txt') #2
    smtp_info = {
        'SMTP_ENCRYPT': 'tls',
        'SMTP_ADDRESS': 'smtp.gmail.com',
        'SMTP_PORT': 587,
        'MAIL_LOGIN': '',
        'MAIL_PASSWORD': '',
    }

    try:
        if smtp_info.get('SMTP_ENCRYPT', "tls"):
            s = smtplib.SMTP(host=smtp_info.get('SMTP_ADDRESS'), port=smtp_info.get('SMTP_PORT'))
            s.starttls()
        else:
            s = smtplib.SMTP_SSL(host=smtp_info.get('SMTP_ADDRESS'), port=smtp_info.get('SMTP_PORT'))
            s.ehlo()

        s.login(smtp_info.get('MAIL_LOGIN'), smtp_info.get('MAIL_PASSWORD'))

        for customer in customers: #3
            customer_name = customer.get('name').lower().title() #4
            
            msg = MIMEMultipart() #5
            message = message_template.substitute(CUSTOMER_NAME=customer_name) #6
            
            msg['From'] = smtp_info.get('MAIL_LOGIN')
            msg['To'] = "{0} <{1}>".format(customer_name, customer.get('email'))
            msg['Subject'] = "Chào {0}. Bạn nhận được một mail từ python".format(customer_name)
            msg.attach(MIMEText(message, 'plain')) #7
            s.send_message(msg) #8
            del msg #9
            logging.info("Gửi mail cho {0} thành công".format(customer.get('email')))

        s.quit() #10
    except smtplib.SMTPException as e: #11
        logging.error("Không thể gửi mail. Chi tiết: {0}".format(e))
  1. Ta lấy danh sách customers từ listmails.txt bằng function get_customer_information chúng ta đã viết trước đó và gán vào variable customers
  2. Cũng như trên ta lấy nội dung của templatemail.txt và gán vào biến message_template
  3. Để gửi cho toàn bộ customers, chúng ta sử dụng vòng lặp ở đây. Vòng lặp customer sẽ chạy từ customer đầu tiên đến customer cuối cùng.
  4. Tên khách hàng sẽ viết hoa chữ đầu của mỗi chữ. Để chắc chắn đúng format mình sẽ chuyển tất cả về viết thường bằng method .lower(), và viết hoa chữ đầu bằng method .title()
  5. Ta tạo một đối tượng MIMEMultipart và gán vào biến msg
  6. Đây là cách chúng ta gán tên customer vào CUSTOMER_NAME trong mail template bằng string templates
  7. Sau đó ta attach nội dung mail vào msg với định dạng plain text.
  8. Sau khi mọi thứ được đưa vào msg, python đã sẵn sàng gửi mail bằng function send_message
  9. Để chắc chắn msg ở vòng lặp kế tiếp không bị sai dữ liệu, ta nên xóa nó đi.
  10. Cuối cùng sau khi gửi mail hoàn tất, chúng ta nên đóng kết nối đến smtp server
  11. Trong khi gửi mail, đôi khi có sự cố không thể gửi mail được, chúng ta sẽ theo dõi lỗi bằng try .. except.

Bài viết hướng dẫn gửi mail trong python đến đây là kết thúc. Mọi ý kiến góp ý của các bạn mình rất hoan nghênh. Các bạn thắc mắc có thể hỏi mình bằng cách comment tại bài viết này hoặc trên group Python Community Viet Nam

Link github: https://github.com/kikyo2006/send-mail-in-python

Các thẻ
Bài viết liên quan
1 nhận xét

    Nhận xét mới

    bắt buộc

    yu.kusanagi
    Từ Anh Vũ
    Hồ Chí Minh, Việt Nam

    Xin chào, tôi tên Từ Anh Vũ và là 1 free lancer developer và ngôn ngữ code yêu thích của tôi là Python và PHP. Công việc chủ yếu là viết các module cho magento, magento2, wordpress, django, flask và các framework khác
    Nếu bạn muốn trao đổi với tôi hoặc muốn thuê tôi làm việc cho dự án của bạn, hãy liên hệ với tôi

    ĐĂNG KÝ NHẬN BÀI MỚI

    Tweets gần đây
    Tác giả
    Feeds
    RSS / Atom
    ADVERTISING

    Đăng ký nhận bài viết mới tại hocpython.com?

    Hãy đăng ký nhận bài viết mới tại hocpython.com để:

    • Không bỏ lỡ các bài tutorials mới tại hocpython.com!
    • Cập nhật các công nghệ mới trong python!

    Chỉ cần điền email và họ tên của bạn và nhấn Đăng ký nhận tin!