Nhờ Claude viết script Python gửi hoá đơn PDF cho từng khách hàng

Hướng dẫn nhờ Claude viết script Python gửi email kèm hoá đơn PDF cho từng khách hàng từ file CSV, có chế độ chạy thử và cách kiểm an toàn.

Lập trình với AIĐộ khó: Nâng cao

Kết quả bạn sẽ có

Cuối tháng, kế toán phải gửi hoá đơn PDF cho vài chục khách hàng: mở từng email, gõ tên, đính kèm đúng file, kiểm lại, mà chỉ cần đính nhầm một file là lộ thông tin của khách này cho khách khác.

Sau bài này, bạn có một script Python (đoạn mã nhỏ chạy trên máy tính) do Claude viết: đọc danh sách khách hàng, tìm đúng file hoá đơn, gửi email, báo file nào thiếu, gộp mọi hoá đơn thành một file để lưu, và có chế độ chạy thử để kiểm kỹ trước khi gửi thật.

Cửa sổ Command Prompt chạy script gui_hoa_don.py ở chế độ thử, báo gửi 3 email và 1 file hoá đơn bị thiếu
Script chạy ở chế độ thử: báo từng hoá đơn và file bị thiếu

Đọc xong bạn làm được:

  • Nhờ Claude viết script đọc danh sách CSV và gửi đúng hoá đơn PDF cho từng khách.
  • Đọc script và hiểu dòng chốt an toàn chọn người nhận.
  • Chạy thử ba lượt "xem", "thu", "that" trước khi gửi thật.
  • Hỏi Claude để sửa lỗi khi script báo lỗi.
Cần gì, mất bao lâu

Công cụ: Python (miễn phí, tải ở python.org), thư viện pypdf, Claude (gói miễn phí viết được script này) và một tài khoản Gmail có xác minh 2 bước.

Dữ liệu cần chuẩn bị: thư mục chứa các file hoá đơn PDF đặt tên theo mã khách hàng, và file danh sách khách hàng dạng CSV.

Thời gian: chuẩn bị và dựng script một lần, rồi chạy thử ba lượt trước khi gửi thật.

Chuẩn bị máy và dữ liệu

Bạn cần ba thứ:

1. Python trên máy tính. Tải bản mới nhất tại python.org [5]. Khi cài trên Windows, nhớ tích ô "Add python.exe to PATH" ở màn hình đầu tiên. Cài xong, mở Command Prompt và gõ:

pip install pypdf

Lệnh này cài thư viện pypdf để đọc và gộp file PDF [2].

2. Một thư mục làm việc, ví dụ D:\GuiHoaDon, gồm:

  • Thư mục con hoa_don chứa các file PDF, đặt tên theo mã khách hàng: KH001.pdf, KH002.pdf...
  • File danh_sach.csv có 3 cột: ma_khach_hang, ten_khach_hang, email. Bạn tạo trong Excel rồi chọn File > Save As > kiểu CSV UTF-8 để giữ đúng chữ tiếng Việt.
ma_khach_hang ten_khach_hang email
KH001 Công ty An Phát ketoan@anphat.vn
KH002 Cửa hàng Minh Châu minhchau@gmail.com

3. Tài khoản Gmail dùng để gửi, đã bật xác minh 2 bước và tạo mật khẩu ứng dụng (app password, một mật khẩu 16 ký tự chỉ dùng cho script) [3]. Không bao giờ đặt mật khẩu Gmail thật vào script. Tài khoản Gmail công ty có thể bị quản trị viên tắt tính năng này, khi đó hãy hỏi bộ phận IT.

Trước khi bắt đầu

Hỏi công ty có cho phép gửi email tự động bằng tài khoản của bạn không.

Không dán danh sách khách hàng thật vào Claude. Chỉ mô tả tên cột, Claude không cần thấy dữ liệu để viết script.

Nhờ Claude viết script

Mở Claude. Câu lệnh tốt cần mô tả rõ dữ liệu vào, việc cần làm, và các trường hợp lỗi. Muốn viết câu lệnh chặt hơn, xem cấu trúc câu lệnh 4 phần.

Viết script gửi hoá đơnMở Claude (mở tab mới)
Tôi là nhân viên kế toán, không biết lập trình. Viết giúp tôi một script Python chạy trên Windows:
- Đọc file danh_sach.csv (UTF-8, có BOM vì lưu từ Excel) gồm các cột: ma_khach_hang, ten_khach_hang, email.
- Với mỗi khách, tìm file hoa_don/[ma_khach_hang].pdf, gửi email qua Gmail (SMTP, dùng mật khẩu ứng dụng) với tiêu đề "Hoá đơn tháng [10/2026] - [tên khách]" và đính kèm file đó.
- Nếu thiếu file hoặc file hỏng, in cảnh báo và bỏ qua khách đó, không dừng cả chương trình.
- Gộp tất cả hoá đơn đã gửi thành một file tong_hop_hoa_don.pdf bằng thư viện pypdf.
- Có biến CHE_DO với 3 giá trị: "xem" (chỉ in ra màn hình, không gửi), "thu" (gửi tất cả về email của tôi), "that" (gửi cho khách). Mặc định là "xem".
- Nghỉ 2 giây giữa mỗi email.
- Đặt các thông tin cần sửa (email, mật khẩu, tháng) ở đầu file, có chú thích tiếng Việt.
Sau đó giải thích từng phần script bằng tiếng Việt cho người mới, và hướng dẫn tôi chạy.

Ba yêu cầu quan trọng nhất trong câu lệnh: chế độ chạy thử, bỏ qua lỗi thay vì dừng, và nghỉ giữa các email. Gmail có thể tạm khoá quyền gửi nếu bạn gửi quá 500 email trong một ngày [4], nên đừng dùng script này cho danh sách lớn.

Đọc và đối chiếu script

Đừng chạy code bạn chưa đọc. Script Claude viết sẽ không giống hệt từng chữ, nhưng nên có đủ các phần như bản mẫu dưới đây (đã chạy thử). Bạn có thể dán bản này vào Claude và hỏi: "So sánh script của bạn với bản này, khác nhau ở đâu?"

import csv
import smtplib
import time
from email.message import EmailMessage
from pathlib import Path

from pypdf import PdfReader, PdfWriter

# CHE_DO: "xem" = chỉ in ra màn hình, "thu" = gửi hết về email của bạn, "that" = gửi cho khách
CHE_DO = "xem"
EMAIL_GUI = "ten.ban@gmail.com"
MAT_KHAU_UNG_DUNG = ""  # mật khẩu ứng dụng 16 ký tự, không phải mật khẩu Gmail
EMAIL_THU = "ten.ban@gmail.com"

THU_MUC = Path("hoa_don")
DANH_SACH = Path("danh_sach.csv")
FILE_GOP = Path("tong_hop_hoa_don.pdf")

def tao_email(dong, file_pdf, nguoi_nhan):
    thu = EmailMessage()
    thu["From"] = EMAIL_GUI
    thu["To"] = nguoi_nhan
    thu["Subject"] = f"Hoá đơn tháng 10/2026 - {dong['ten_khach_hang']}"
    thu.set_content(
        f"Kính gửi {dong['ten_khach_hang']},\n\n"
        "Công ty xin gửi Quý khách hoá đơn tháng 10/2026 trong file đính kèm.\n"
        "Nếu có thắc mắc, Quý khách vui lòng trả lời email này.\n\n"
        "Trân trọng."
    )
    thu.add_attachment(file_pdf.read_bytes(), maintype="application",
                       subtype="pdf", filename=file_pdf.name)
    return thu

def main():
    with DANH_SACH.open(encoding="utf-8-sig", newline="") as f:
        danh_sach = list(csv.DictReader(f))

    may_chu = None
    if CHE_DO in ("thu", "that"):
        may_chu = smtplib.SMTP_SSL("smtp.gmail.com", 465)
        may_chu.login(EMAIL_GUI, MAT_KHAU_UNG_DUNG)

    gop = PdfWriter()
    da_gui, loi = 0, 0
    for dong in danh_sach:
        file_pdf = THU_MUC / f"{dong['ma_khach_hang']}.pdf"
        if not file_pdf.exists():
            print(f"THIẾU FILE  {file_pdf}  ({dong['ten_khach_hang']})")
            loi += 1
            continue
        try:
            so_trang = len(PdfReader(file_pdf).pages)
        except Exception as e:
            print(f"FILE HỎNG   {file_pdf}: {e}")
            loi += 1
            continue

        gop.append(str(file_pdf))
        nguoi_nhan = dong["email"] if CHE_DO == "that" else EMAIL_THU
        print(f"{CHE_DO.upper():5} {file_pdf.name} ({so_trang} trang) -> {nguoi_nhan}")

        if may_chu:
            may_chu.send_message(tao_email(dong, file_pdf, nguoi_nhan))
            da_gui += 1
            time.sleep(2)

    if may_chu:
        may_chu.quit()
    gop.write(FILE_GOP)
    print(f"Xong: gửi {da_gui} email, {loi} lỗi. File gộp: {FILE_GOP}")

if __name__ == "__main__":
    main()

Những chỗ cần để ý khi đọc:

  • Dòng nguoi_nhan = ...: chỉ khi CHE_DO là "that" mới lấy email khách. Mọi chế độ khác đều gửi về email của bạn. Đây là chốt an toàn quan trọng nhất.
  • encoding="utf-8-sig": đọc đúng file CSV lưu từ Excel, không bị lỗi chữ tiếng Việt.
  • EmailMessage và add_attachment: cách gửi email kèm file theo tài liệu chính thức của Python [1].
  • gop.append(...): cách pypdf gộp nhiều file PDF thành một [2].

Chỗ nào không hiểu, hỏi Claude: "Dòng này làm gì? Nếu xoá nó thì sao?"

Chạy thử ba lượt

Lưu script thành file gui_hoa_don.py trong thư mục làm việc. Mở Command Prompt, gõ cd /d D:\GuiHoaDon để vào thư mục, rồi chạy python gui_hoa_don.py.

Lượt 1, CHE_DO = "xem": script không gửi gì cả, chỉ in danh sách. Kết quả trông như sau:

XEM   KH001.pdf (1 trang) -> ten.ban@gmail.com
XEM   KH002.pdf (2 trang) -> ten.ban@gmail.com
THIẾU FILE  hoa_don\KH003.pdf  (Công ty Hoà Bình)
FILE HỎNG   hoa_don\KH004.pdf: Stream has ended unexpectedly
Xong: gửi 0 email, 2 lỗi. File gộp: tong_hop_hoa_don.pdf

Kiểm: số khách khớp với danh sách, file nào báo thiếu thì bổ sung. Mở file tong_hop_hoa_don.pdf xem đủ trang chưa.

Lượt 2, CHE_DO = "thu": điền email và mật khẩu ứng dụng ở đầu file. Tất cả email sẽ về hộp thư của bạn. Mở vài email, kiểm tiêu đề có đúng tên khách, file đính kèm có đúng mã khách không.

Lượt 3, CHE_DO = "that": chỉ chuyển sang chế độ này khi lượt 2 đã đúng hoàn toàn. Lần đầu, nên thử với danh sách chỉ 2 đến 3 khách quen trước.

Hỏi Claude khi script báo lỗi

Lỗi là chuyện bình thường. Chép nguyên văn dòng báo lỗi (thường là vài dòng cuối, bắt đầu bằng chữ Error) và hỏi Claude:

Sửa lỗi scriptMở Claude (mở tab mới)
Script gửi hoá đơn của tôi báo lỗi khi chạy ở chế độ [xem / thu]:
[dán nguyên văn thông báo lỗi]
Giải thích lỗi này nghĩa là gì bằng tiếng Việt đơn giản, nguyên nhân có thể, và tôi cần sửa gì. Nếu phải sửa script, chỉ đưa đúng đoạn cần sửa.

Đọc tiếp: làm báo cáo chi phí gửi sếp cuối tuần, xem báo cáo chi phí hằng tuần bằng Excel và ChatGPT. Muốn nhờ AI viết đúng ý ngay từ lần đầu, xem cấu trúc câu lệnh 4 phần.

  • Danh sách lưu đúng kiểu CSV UTF-8, tên file PDF trùng mã khách hàng
  • Dùng mật khẩu ứng dụng, không dùng mật khẩu Gmail thật
  • Đã đọc script và hiểu dòng chọn người nhận
  • Chạy lượt "xem", rồi "thu", kiểm kỹ trước khi chạy "that"
  • Lần gửi thật đầu tiên chỉ thử với 2 đến 3 khách
  • Không gửi quá vài trăm email mỗi ngày từ một tài khoản Gmail

Sửa các lỗi thường gặp

  • ModuleNotFoundError: No module named 'pypdf': chưa chạy lệnh pip install pypdf.
  • SMTPAuthenticationError: sai email hoặc mật khẩu ứng dụng, hoặc tài khoản chưa bật xác minh 2 bước [3]. Tài khoản Gmail công ty có thể bị quản trị viên tắt mật khẩu ứng dụng, khi đó hỏi bộ phận IT.
  • FileNotFoundError: danh_sach.csv: bạn chưa cd vào đúng thư mục chứa file.
  • Báo THIẾU FILE hoặc FILE HỎNG ở lượt "xem": tên file PDF chưa trùng mã khách hàng, hoặc file bị hỏng. Bổ sung hoặc xuất lại file đó rồi chạy lại lượt "xem" trước khi gửi thật.

Nguồn tham khảo

  1. Python · email: Examples (tài liệu chính thức)
  2. pypdf · Merging PDF files (tài liệu chính thức)
  3. Google Account Help · Sign in with app passwords (trang chính thức)
  4. Gmail Help · Gmail sending limits (trang chính thức)
  5. Python · Download Python (trang chính thức)

Khánh

AI Practitioner

Tác giả chuỗi bài viết ứng dụng trí tuệ nhân tạo vào công việc văn phòng thực tế tại Việt Nam. Triết lý của tôi là "AI, applied.": biến những thuật ngữ phức tạp thành công cụ làm việc nhẹ nhàng, nhanh chóng và chính xác.