E-postaları Programlı Olarak Okuma ve Gönderme
Mesajları listeleme, mesaj gövdesini alma ve MIME e-postaları gönderme.
E-postaları Programlı Olarak Okuma ve Gönderme, CoddyKit'te ücretsiz bir AI Agents dersidir. Bu, 4 dersinin 2. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, AI Agents öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. AI Agents kursu toplamda 4 dersten oluşur.
Gmail API'siyle İletileri Listeleme
E-posta okumadaki ilk adım, ölçütlerinize uyan iletileri listelemektir. service.users().messages().list(), tam içeriği değil, ileti kimliklerini ve ileti dizisi kimliklerini döndürür. Ardından her iletiyi ayrı ayrı getirirsiniz. Bu iki adımlı düzenek, listeleme çağrısını hızlı tutar.
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')Tam Bir İletiyi Getirme
Tam ileti içeriğini almak için service.users().messages().get() kullanın. format parametresi ne kadar veri döndürüleceğini belirler: 'full' üst bilgileri ve gövdeyi içerir, 'metadata' yalnızca üst bilgileri döndürür, 'minimal' ise yalnızca kimlikleri ve etiketleri döndürür.
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])E-posta Üst Bilgilerini Çıkarma
Üst bilgiler (Gönderen, Alıcı, Konu, Tarih), message['payload']['headers'] içinde {'name': ..., 'value': ...} sözlüklerinden oluşan bir liste olarak saklanır. Üst bilgileri ada göre çıkarmak için bir yardımcı yazın; bunu sürekli kullanacaksınız.
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"]}')E-posta Gövdesinin Kodunu Çözme (base64)
Gmail API'sindeki e-posta gövdeleri base64url ile kodlanır; bu, + karakterinin - ve / karakterinin _ olduğu, URL'lerde güvenli bir base64 çeşididir. Kodu çözmek için base64.urlsafe_b64decode() kullanın. Hem basit (tek parçalı) hem de çok parçalı e-postaları işleyin.
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))
Çok Parçalı E-postaları Özyinelemeli İşleme
Karmaşık e-postalar (ekler, satır içi görseller veya karma içerik içerenler) iç içe geçmiş çok parçalı yapılardır. Gövde parçaları istenildiği kadar derine iç içe olabilir. Parça ağacını dolaşan özyinelemeli bir işlev tüm durumları işler.
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])İletileri Okundu Olarak İşaretleme
Bir e-postayı işledikten sonra ajanınız UNREAD etiketini kaldırarak iletiyi okundu olarak işaretlemelidir. removeLabelIds=['UNREAD'] ile service.users().messages().modify() kullanın. Ajan tarafından işlenen e-postaları izlemek için PROCESSED gibi etiketler de ekleyebilirsiniz.
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'))
MIME Metniyle E-posta Oluşturma
E-posta göndermek için önce Python'ın standart email kitaplığını kullanarak MIME iletisi olarak oluşturun. Ardından ham baytları base64url ile kodlayın ve Gmail API'sine POST edin. MIMEText, ileti gövdesinin doğru biçimde kodlanmasını sağlar.
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'siyle E-posta Gönderme
Oluşturduğunuz iletiyi service.users().messages().send() kullanarak gönderin. userId='me' parametresi, kimliği doğrulanmış kullanıcıyı belirtir. API, gönderilen iletiyi kimliği ve ileti dizisi kimliğiyle birlikte döndürür.
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)Taslak E-postalar Oluşturma ve Gönderme
Ajanlar hemen göndermek yerine insanların incelemesi için drafts oluşturabilir. service.users().drafts().create() kullanın. Bir insan daha sonra taslağı inceleyip Gmail kullanıcı arayüzünden gönderebilir. İnsan onayı gerektiren tüm e-postalar için önerilen düzenek budur.
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'])Birden Çok E-postayı Toplu İşleme
Çok sayıda e-postayı işlerken bunları sıkı bir döngüde tek tek getirmeyin; kota sınırlarına ulaşırsınız. Küçük gecikmeler içeren denetimli bir döngü veya birden çok işlemi tek bir HTTP çağrısında birleştirmek için Gmail API'sinin toplu istek özelliğini kullanın.
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 processedBir E-postayı Yanıtlama (İleti Dizisi İçinde)
İleti dizisi içinde yanıt göndermek için In-Reply-To ve References üst bilgilerini özgün iletinin Message-ID üst bilgisine ayarlayın ve gönderme çağrısına threadId değerini geçirin. Böylece yanıt aynı Gmail konuşma dizisinde kalır.
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
}Hızlı Sınama: base64 E-posta Gövdesi
Gmail API'sinde ileti işlemeyi ne kadar anladığınızı sınayın.
E-posta Okuma ve Gönderme Özeti
Ajanınız artık e-postaları program aracılığıyla okuyup gönderebilir:
- Listele:
messages().list(q='is:unread')kimlikleri döndürür; Gmail arama söz dizimini kullanın - Getir:
messages().get(id=..., format='full')tam iletiyi döndürür - Üst bilgileri ayrıştır: Gönderen/Konu/Tarih bilgilerini
payload.headersiçinden çıkarın - Gövdenin kodunu çöz: Metin için
base64.urlsafe_b64decode(data)kullanın; çok parçalı bölümlerde özyinelemeli olarak ilerleyin - Gönder:
MIMETextile oluşturun, base64url ile kodlayın vemessages().send()üzerinden POST edin - İleti dizisinde yanıtla: Gönderme gövdesinde
In-Reply-Toüst bilgisini vethreadIddeğerini ayarlayın
Sıkça Sorulan Sorular
“E-postaları Programlı Olarak Okuma ve Gönderme” dersi ücretsiz mi?
Evet — “E-postaları Programlı Olarak Okuma ve Gönderme” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve AI Agents kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. AI Agents kursu toplamda 4 dersten oluşur.
“E-postaları Programlı Olarak Okuma ve Gönderme” dersinde ne öğreneceğim?
Mesajları listeleme, mesaj gövdesini alma ve MIME e-postaları gönderme. AI Agents ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.
AI Agents öğrenmeye başlamak için deneyim gerekli mi?
Önceden deneyim gerekmez. CoddyKit'te AI Agents, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 2. dersidir.
“E-postaları Programlı Olarak Okuma ve Gönderme” dersi ne kadar sürer?
Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.
Bu AI Agents dersinde kod yazıp çalıştırabilir miyim?
Evet. Her AI Agents dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.
Bu kursun tüm dersleri
- API Üzerinden Gmail'e Bağlanma
- E-postaları Programlı Olarak Okuma ve Gönderme
- Takvim Etkinliği Oluşturma ve Sorgulama
- Basit Bir E-posta Asistanı Aracısı Oluşturma