Ejen AI · Pelajaran

Membaca dan Menghantar E-mel Secara Terprogram

Menyenaraikan mesej, mendapatkan isi mesej dan menghantar e-mel MIME.

Pelajaran 2 daripada 413 langkah

Membaca dan Menghantar E-mel Secara Terprogram ialah pelajaran Ejen AI percuma di CoddyKit. Ini ialah pelajaran 2 daripada 4. Anda boleh membaca keseluruhan pelajaran di bawah secara percuma — kemudian berlatih secara praktikal dalam pelayar menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Ejen AI, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Ejen AI merangkumi sejumlah 4 pelajaran.

Menyenaraikan Mesej dengan API Gmail

Langkah pertama untuk membaca e-mel ialah menyenaraikan mesej yang sepadan dengan kriteria anda. service.users().messages().list() mengembalikan ID mesej dan ID utas — bukan kandungan penuh. Kemudian, dapatkan setiap mesej secara berasingan. Corak dua langkah ini memastikan panggilan penyenaraian kekal pantas.

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')

Mendapatkan Mesej Penuh

Gunakan service.users().messages().get() untuk mendapatkan kandungan mesej penuh. Parameter format mengawal jumlah data yang dikembalikan: 'full' merangkumi pengepala dan kandungan, 'metadata' hanya mengembalikan pengepala dan 'minimal' hanya mengembalikan ID serta label.

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])

Mengekstrak Pengepala E-mel

Pengepala (Daripada, Kepada, Subjek, Tarikh) disimpan dalam message['payload']['headers'] sebagai senarai kamus {'name': ..., 'value': ...}. Tulis fungsi pembantu untuk mengekstrak pengepala mengikut nama — anda akan menggunakannya dengan kerap.

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"]}')

Menyahkod Kandungan E-mel (base64)

Kandungan e-mel dalam API Gmail dikodkan dengan base64url — varian base64 yang selamat untuk URL, apabila + menjadi - dan / menjadi _. Gunakan base64.urlsafe_b64decode() untuk menyahkod. Kendalikan kedua-dua e-mel ringkas (satu bahagian) dan e-mel berbilang bahagian.

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))

Mengendalikan E-mel Berbilang Bahagian Secara Rekursif

E-mel kompleks (dengan lampiran, imej sebaris atau kandungan bercampur) terdiri daripada struktur berbilang bahagian yang bersarang. Bahagian kandungan boleh bersarang pada kedalaman yang tidak terhad. Fungsi rekursif yang merentasi pepohon bahagian boleh mengendalikan semua keadaan.

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])

Menandakan Mesej sebagai Telah Dibaca

Selepas memproses e-mel, ejen anda hendaklah menandakannya sebagai telah dibaca dengan membuang label UNREAD. Gunakan service.users().messages().modify() dengan removeLabelIds=['UNREAD']. Anda juga boleh menambah label seperti PROCESSED untuk menjejaki e-mel yang telah dikendalikan oleh ejen.

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'))

Mengarang E-mel dengan Teks MIME

Untuk menghantar e-mel, karang dahulu e-mel itu sebagai mesej MIME menggunakan pustaka standard Python email. Kemudian kodkan bait mentah menggunakan base64url dan POST e-mel tersebut kepada API Gmail. MIMEText mengendalikan pengekodan kandungan mesej dengan betul.

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']))

Menghantar E-mel dengan API Gmail

Hantar mesej yang telah dikarang menggunakan service.users().messages().send(). Parameter userId='me' merujuk kepada pengguna yang disahkan. API mengembalikan mesej yang dihantar bersama ID dan ID utasnya.

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)

Mencipta dan Menghantar Draf E-mel

Daripada menghantar serta-merta, ejen boleh mencipta draf untuk semakan manusia. Gunakan service.users().drafts().create(). Manusia kemudiannya boleh menyemak dan menghantar draf tersebut daripada antara muka Gmail. Ini ialah corak yang disyorkan untuk mana-mana e-mel yang memerlukan kelulusan manusia.

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'])

Memproses Berbilang E-mel secara Kelompok

Apabila memproses banyak e-mel, jangan dapatkannya satu demi satu dalam gelung rapat — anda akan mencapai had kuota. Gunakan gelung terkawal dengan kelewatan singkat atau ciri permintaan kelompok API Gmail untuk menggabungkan beberapa operasi ke dalam satu panggilan 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

Membalas E-mel (Dalam Utas)

Untuk menghantar balasan dalam utas, tetapkan pengepala In-Reply-To dan References kepada pengepala Message-ID mesej asal, kemudian hantar threadId kepada panggilan penghantaran. Dengan cara ini, balasan kekal dalam utas perbualan Gmail yang sama.

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
    }

Semakan Pantas: Kandungan E-mel base64

Uji pemahaman anda tentang pengendalian mesej API Gmail.

Ringkasan Membaca dan Menghantar E-mel

Ejen anda kini boleh membaca dan menghantar e-mel secara terprogram:

  • Senaraikan: messages().list(q='is:unread') mengembalikan ID; gunakan sintaks carian Gmail
  • Dapatkan: messages().get(id=..., format='full') mengembalikan mesej penuh
  • Huraikan pengepala: ekstrak pengepala Daripada/Subjek/Tarikh daripada payload.headers
  • Nyahkod kandungan: base64.urlsafe_b64decode(data) untuk teks; lakukan rekursi terhadap bahagian berbilang bahagian
  • Hantar: karang dengan MIMEText, kodkan menggunakan base64url dan POST melalui messages().send()
  • Balas dalam utas: tetapkan pengepala In-Reply-To + threadId dalam isi penghantaran
Percuma untuk bermula

Pelajari Ejen AI dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
60
Pelajaran
239

Soalan Lazim

Adakah pelajaran “Membaca dan Menghantar E-mel Secara Terprogram” percuma?

Ya — teks penuh “Membaca dan Menghantar E-mel Secara Terprogram” boleh dibaca secara percuma di web ini. Untuk berlatih secara interaktif menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7, serta membuka kunci baki kursus Ejen AI, tingkat taraf kepada CoddyKit PRO. Kursus Ejen AI merangkumi sejumlah 4 pelajaran.

Apakah yang akan saya pelajari dalam “Membaca dan Menghantar E-mel Secara Terprogram”?

Menyenaraikan mesej, mendapatkan isi mesej dan menghantar e-mel MIME. Anda berlatih Ejen AI menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan Ejen AI?

Tiada pengalaman terdahulu diperlukan. Pembelajaran Ejen AI di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 2 daripada 4.

Berapa lamakah pelajaran “Membaca dan Menghantar E-mel Secara Terprogram” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran Ejen AI ini?

Ya. Setiap pelajaran Ejen AI menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. Menyambung ke Gmail melalui API
  2. Membaca dan Menghantar E-mel Secara Terprogram
  3. Penciptaan dan Pertanyaan Acara Kalendar
  4. Membina Ejen Pembantu E-mel Ringkas
← Kembali ke Ejen AI