0Pricing
AI Agents · บทเรียน

การอ่านและส่งอีเมลด้วยโปรแกรม

แสดงรายการข้อความ ดึงเนื้อหาข้อความ และส่งอีเมล MIME

การอ่านและส่งอีเมลด้วยโปรแกรม เป็นบทเรียน AI Agents ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน AI Agents และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส AI Agents มีบทเรียนทั้งหมด 4 บทเรียน

การแสดงรายการข้อความด้วย Gmail API

ขั้นตอนแรกของการอ่านอีเมลคือการแสดงรายการข้อความที่ตรงตามเกณฑ์ของคุณ service.users().messages().list() จะคืนค่ารหัสข้อความและรหัสเธรด ไม่ใช่เนื้อหาทั้งหมด จากนั้นคุณจึงเรียกดูข้อความแต่ละรายการแยกกัน รูปแบบสองขั้นตอนนี้ช่วยให้การเรียกแสดงรายการทำงานได้รวดเร็ว

def list_messages(service, user_id='me', query='', max_results=10):
    results = service.users().messages().list(
        userId=user_id,
        q=query,          # Gmail search query
        maxResults=max_results
    ).execute()

    messages = results.get('messages', [])
    print(f'Found {len(messages)} messages')
    return messages

# Examples of Gmail search queries:
# 'is:unread' — unread messages
# 'from:boss@company.com is:unread' — unread from boss
# 'subject:invoice label:inbox' — invoices in inbox
# 'after:2026/05/01 has:attachment' — recent with attachments
messages = list_messages(gmail_service, query='is:unread label:inbox')

การดึงข้อความฉบับเต็ม

ใช้ service.users().messages().get() เพื่อดึงเนื้อหาข้อความฉบับเต็ม พารามิเตอร์ format จะควบคุมปริมาณข้อมูลที่ส่งกลับมา โดย 'full' จะรวมส่วนหัวและเนื้อหา 'metadata' จะส่งกลับเฉพาะส่วนหัว และ 'minimal' จะส่งกลับเฉพาะรหัสกับป้ายกำกับ

def get_message(service, message_id, user_id='me'):
    message = service.users().messages().get(
        userId=user_id,
        id=message_id,
        format='full'  # 'full', 'metadata', or 'minimal'
    ).execute()
    return message

# Fetch the first unread message
messages = list_messages(gmail_service, query='is:unread', max_results=1)
if messages:
    msg = get_message(gmail_service, messages[0]['id'])
    print('Thread ID:', msg['threadId'])
    print('Labels:', msg['labelIds'])
    print('Snippet:', msg['snippet'][:100])

การดึงส่วนหัวของอีเมล

ส่วนหัว (ผู้ส่ง ผู้รับ หัวเรื่อง วันที่) ถูกจัดเก็บใน message['payload']['headers'] เป็นรายการดิกชันนารีรูปแบบ {'name': ..., 'value': ...} โปรดเขียนตัวช่วยเพื่อดึงส่วนหัวตามชื่อ เพราะคุณจะใช้ตัวช่วยนี้อยู่เสมอ

def get_header(message, name):
    headers = message.get('payload', {}).get('headers', [])
    for h in headers:
        if h['name'].lower() == name.lower():
            return h['value']
    return ''

def extract_email_meta(message):
    return {
        'id': message['id'],
        'from': get_header(message, 'From'),
        'to': get_header(message, 'To'),
        'subject': get_header(message, 'Subject'),
        'date': get_header(message, 'Date'),
        'snippet': message.get('snippet', '')
    }

meta = extract_email_meta(msg)
print(f'From: {meta["from"]}')
print(f'Subject: {meta["subject"]}')
print(f'Date: {meta["date"]}')

การถอดรหัสเนื้อหาอีเมล (base64)

เนื้อหาอีเมลใน Gmail API จะถูกเข้ารหัสแบบ base64url ซึ่งเป็นรูปแบบของ base64 ที่ปลอดภัยสำหรับ URL โดย + จะกลายเป็น - และ / จะกลายเป็น _ ใช้ base64.urlsafe_b64decode() เพื่อถอดรหัส และรองรับทั้งอีเมลแบบง่าย (ส่วนเดียว) และอีเมลแบบหลายส่วน

import base64

def decode_body(data):
    if not data:
        return ''
    decoded_bytes = base64.urlsafe_b64decode(data + '==')
    return decoded_bytes.decode('utf-8', errors='replace')

def get_email_body(message):
    payload = message.get('payload', {})
    mime_type = payload.get('mimeType', '')

    # Simple (non-multipart) email
    if 'body' in payload and payload['body'].get('data'):
        return decode_body(payload['body']['data'])

    # Multipart email: find the text/plain or text/html part
    parts = payload.get('parts', [])
    for part in parts:
        if part.get('mimeType') == 'text/plain':
            return decode_body(part['body'].get('data', ''))

    # Fallback: try text/html
    for part in parts:
        if part.get('mimeType') == 'text/html':
            return decode_body(part['body'].get('data', ''))

    return message.get('snippet', '')

# --- demo ---
encoded = base64.urlsafe_b64encode(b'Hello from the agent!').decode().rstrip('=')
print('Decoded body:', decode_body(encoded))

message = {
    'payload': {
        'mimeType': 'multipart/alternative',
        'parts': [
            {'mimeType': 'text/plain', 'body': {'data': encoded}}
        ]
    }
}
print('Email body:', get_email_body(message))

การจัดการอีเมลแบบหลายส่วนด้วยการเรียกซ้ำ

อีเมลที่ซับซ้อนซึ่งมีไฟล์แนบ รูปภาพแบบแทรกในเนื้อหา หรือเนื้อหาผสม จะมีโครงสร้างแบบหลายส่วนซ้อนกัน ส่วนต่าง ๆ ของเนื้อหาอาจซ้อนลึกได้โดยไม่มีข้อจำกัด ฟังก์ชันแบบเรียกซ้ำที่เดินสำรวจต้นไม้ของส่วนต่าง ๆ จะจัดการได้ทุกกรณี

import base64

def extract_parts(payload, target_mime='text/plain'):
    parts_text = []
    mime_type = payload.get('mimeType', '')

    if mime_type == target_mime:
        data = payload.get('body', {}).get('data', '')
        if data:
            decoded = base64.urlsafe_b64decode(data + '==').decode('utf-8', errors='replace')
            parts_text.append(decoded)

    # Recurse into sub-parts
    for part in payload.get('parts', []):
        parts_text.extend(extract_parts(part, target_mime))

    return parts_text

def get_plain_text(message):
    payload = message.get('payload', {})
    texts = extract_parts(payload, 'text/plain')
    return '\n\n'.join(texts) if texts else message.get('snippet', '')

body_text = get_plain_text(msg)
print(f'Body ({len(body_text)} chars):', body_text[:200])

การทำเครื่องหมายข้อความว่าอ่านแล้ว

หลังจากประมวลผลอีเมลแล้ว เอเจนต์ควรทำเครื่องหมายว่าอ่านแล้วด้วยการนำป้ายกำกับ UNREAD ออก ใช้ service.users().messages().modify() พร้อมกับ removeLabelIds=['UNREAD'] นอกจากนี้ยังเพิ่มป้ายกำกับอย่าง PROCESSED เพื่อติดตามอีเมลที่เอเจนต์จัดการแล้วได้

def mark_as_read(service, message_id, user_id='me'):
    service.users().messages().modify(
        userId=user_id,
        id=message_id,
        body={'removeLabelIds': ['UNREAD']}
    ).execute()
    print(f'Marked {message_id} as read')

def add_label(service, message_id, label_id, user_id='me'):
    service.users().messages().modify(
        userId=user_id,
        id=message_id,
        body={'addLabelIds': [label_id]}
    ).execute()

# Get label ID by name
def get_label_id(service, label_name, user_id='me'):
    labels = service.users().labels().list(userId=user_id).execute()
    for label in labels.get('labels', []):
        if label['name'].lower() == label_name.lower():
            return label['id']
    return None

# --- demo: minimal stand-in for the Gmail API's service object ---
class _Exec:
    def __init__(self, result):
        self._result = result
    def execute(self):
        return self._result

class _FakeUsers:
    def messages(self):
        return self
    def modify(self, **kwargs):
        print(f'[gmail api] messages.modify({kwargs})')
        return _Exec({'id': kwargs.get('id')})
    def labels(self):
        return self
    def list(self, **kwargs):
        return _Exec({'labels': [{'id': 'Label_1', 'name': 'Processed'}]})

class _FakeService:
    def users(self):
        return _FakeUsers()

service = _FakeService()
mark_as_read(service, 'msg_42')
add_label(service, 'msg_42', 'Label_1')
print('Label id for "Processed":', get_label_id(service, 'Processed'))

การเขียนอีเมลด้วย MIMEText

หากต้องการส่งอีเมล ขั้นแรกให้เขียนอีเมลเป็นข้อความ MIME โดยใช้ไลบรารีมาตรฐาน email ของ Python จากนั้นเข้ารหัสไบต์ดิบเป็น base64url และส่งด้วย POST ไปยัง Gmail API MIMEText จะจัดการการเข้ารหัสเนื้อหาข้อความอย่างถูกต้อง

import base64
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

def create_message(sender, to, subject, body_text, body_html=None):
    if body_html:
        msg = MIMEMultipart('alternative')
        msg.attach(MIMEText(body_text, 'plain', 'utf-8'))
        msg.attach(MIMEText(body_html, 'html', 'utf-8'))
    else:
        msg = MIMEText(body_text, 'plain', 'utf-8')

    msg['From'] = sender
    msg['To'] = to
    msg['Subject'] = subject

    # Encode as base64url
    raw = base64.urlsafe_b64encode(msg.as_bytes()).decode('utf-8')
    return {'raw': raw}

message = create_message(
    sender='agent@yourcompany.com',
    to='recipient@example.com',
    subject='Weekly Summary',
    body_text='Hello,\n\nHere is your summary.\n\nBest,\nAgent'
)

# --- demo ---
print('Message keys:', list(message.keys()))
print('Base64 length:', len(message['raw']))

การส่งอีเมลด้วย Gmail API

ส่งข้อความที่เขียนไว้ด้วย service.users().messages().send() พารามิเตอร์ userId='me' หมายถึงผู้ใช้ที่ยืนยันตัวตนแล้ว API จะคืนค่าข้อความที่ส่ง พร้อมรหัสข้อความและรหัสเธรด

from googleapiclient.errors import HttpError

def send_message(service, message, user_id='me'):
    try:
        sent = service.users().messages().send(
            userId=user_id,
            body=message
        ).execute()
        print(f'Message sent! ID: {sent["id"]}')
        return sent
    except HttpError as e:
        import json
        body = json.loads(e.content.decode())
        print(f'Send failed ({e.resp.status}): {body.get("error", {}).get("message")}')
        return None

# Send the message
message = create_message(
    sender='me',
    to='team@company.com',
    subject='Agent Report',
    body_text='Processing complete. 42 tasks handled.'
)
send_message(gmail_service, message)

การสร้างและส่งอีเมลฉบับร่าง

แทนที่จะส่งทันที เอเจนต์สามารถสร้างฉบับร่างให้มนุษย์ตรวจสอบได้ ใช้ service.users().drafts().create() จากนั้นมนุษย์สามารถตรวจสอบและส่งฉบับร่างผ่านส่วนติดต่อผู้ใช้ของ Gmail วิธีนี้เป็นรูปแบบที่แนะนำสำหรับอีเมลทุกฉบับที่ต้องได้รับการอนุมัติจากมนุษย์

def create_draft(service, message, user_id='me'):
    draft = service.users().drafts().create(
        userId=user_id,
        body={'message': message}
    ).execute()
    print(f'Draft created: {draft["id"]}')
    return draft

def send_draft(service, draft_id, user_id='me'):
    sent = service.users().drafts().send(
        userId=user_id,
        body={'id': draft_id}
    ).execute()
    print(f'Draft sent as message: {sent["id"]}')
    return sent

# Create a draft for review
message = create_message(
    sender='me',
    to='client@example.com',
    subject='Proposal Follow-up',
    body_text='Dear Client,\n\nFollowing up on our proposal...'
)
draft = create_draft(gmail_service, message)
# Human reviews in Gmail, then agent sends:
# send_draft(gmail_service, draft['id'])

การประมวลผลอีเมลหลายฉบับเป็นกลุ่ม

เมื่อประมวลผลอีเมลจำนวนมาก อย่าดึงข้อมูลทีละฉบับในลูปที่ถี่เกินไป เพราะจะทำให้ถึงขีดจำกัดโควตา ใช้ลูปที่ควบคุมจังหวะและมีการหน่วงเวลาเล็กน้อย หรือใช้ความสามารถในการส่งคำขอแบบกลุ่มของ Gmail API เพื่อรวมการดำเนินการหลายรายการไว้ในการเรียก HTTP ครั้งเดียว

import time

def process_unread_emails(service, max_emails=20):
    messages = list_messages(
        service,
        query='is:unread label:inbox',
        max_results=max_emails
    )

    processed = []
    for i, msg_ref in enumerate(messages):
        # Rate-limit: process max 5 per second
        if i > 0 and i % 5 == 0:
            time.sleep(1)

        msg = get_message(service, msg_ref['id'])
        meta = extract_email_meta(msg)
        body = get_plain_text(msg)

        result = {
            'id': msg['id'],
            'from': meta['from'],
            'subject': meta['subject'],
            'body_preview': body[:200]
        }
        processed.append(result)
        mark_as_read(service, msg['id'])

    return processed

การตอบกลับอีเมล (ภายในเธรด)

หากต้องการส่งการตอบกลับภายในเธรด ให้ตั้งค่าส่วนหัว In-Reply-To และ References เป็นค่าส่วนหัว Message-ID ของข้อความต้นฉบับ และส่ง threadId ไปกับการเรียกส่ง วิธีนี้จะทำให้การตอบกลับอยู่ในเธรดการสนทนาเดียวกันของ Gmail

import base64
from email.mime.text import MIMEText

def create_reply(original_message, reply_text, sender='me'):
    original_msg_id = get_header(original_message, 'Message-ID')
    to = get_header(original_message, 'From')
    subject = get_header(original_message, 'Subject')
    if not subject.startswith('Re:'):
        subject = 'Re: ' + subject

    msg = MIMEText(reply_text, 'plain', 'utf-8')
    msg['From'] = sender
    msg['To'] = to
    msg['Subject'] = subject
    msg['In-Reply-To'] = original_msg_id
    msg['References'] = original_msg_id

    raw = base64.urlsafe_b64encode(msg.as_bytes()).decode('utf-8')
    return {
        'raw': raw,
        'threadId': original_message['threadId']  # keeps it in thread
    }

แบบทดสอบสั้น ๆ: เนื้อหาอีเมลแบบ base64

ทดสอบความเข้าใจเกี่ยวกับการจัดการข้อความของ Gmail API

สรุปการอ่านและส่งอีเมล

ขณะนี้เอเจนต์ของคุณสามารถอ่านและส่งอีเมลผ่านโปรแกรมได้แล้ว:

  • แสดงรายการ: messages().list(q='is:unread') จะคืนค่ารหัสข้อความ ให้ใช้ไวยากรณ์การค้นหาของ Gmail
  • ดึงข้อมูล: messages().get(id=..., format='full') จะคืนค่าข้อความฉบับเต็ม
  • แยกส่วนหัว: ดึงผู้ส่ง/หัวเรื่อง/วันที่จาก payload.headers
  • ถอดรหัสเนื้อหา: ใช้ base64.urlsafe_b64decode(data) สำหรับข้อความ และเรียกซ้ำในส่วนต่าง ๆ ของอีเมลแบบหลายส่วน
  • ส่ง: เขียนด้วย MIMEText เข้ารหัสเป็น base64url แล้วส่งด้วย POST ผ่าน messages().send()
  • ตอบกลับในเธรด: ตั้งค่าส่วนหัว In-Reply-To และเพิ่ม threadId ในเนื้อหาการส่ง

คำถามที่พบบ่อย

บทเรียน “การอ่านและส่งอีเมลด้วยโปรแกรม” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การอ่านและส่งอีเมลด้วยโปรแกรม” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส AI Agents ให้อัปเกรดเป็น CoddyKit PRO คอร์ส AI Agents มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การอ่านและส่งอีเมลด้วยโปรแกรม”

แสดงรายการข้อความ ดึงเนื้อหาข้อความ และส่งอีเมล MIME คุณปฏิบัติ AI Agents ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน AI Agents หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน AI Agents บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน

บทเรียน “การอ่านและส่งอีเมลด้วยโปรแกรม” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน AI Agents นี้ได้ไหม

ได้ บทเรียน AI Agents ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. การเชื่อมต่อ Gmail ผ่าน API
  2. การอ่านและส่งอีเมลด้วยโปรแกรม
  3. การสร้างและค้นหาเหตุการณ์ในปฏิทิน
  4. การสร้างตัวแทนผู้ช่วยอีเมลอย่างง่าย
← กลับไปที่ AI Agents