A working setup to send and read Gmail programmatically using Python, without browser automation or OAuth setup — just an App Password.
- Gmail account with 2-Step Verification enabled
- App Password generated at https://myaccount.google.com/apppasswords
- Python 3 built-ins (
smtplib,imaplib,email)
- Go to https://myaccount.google.com/apppasswords
- Select "Mail" and your device
- Copy the 16-char password (e.g.
jfff kdzn llka srvw)
export GMAIL_EMAIL="your.email@gmail.com"
export GMAIL_APP_PASSWORD="jfff kdzn llka srvw"import smtplib, os
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
def send_email(sender, password, to, subject, body, attachment_path=None):
msg = MIMEMultipart("alternative")
msg["From"] = sender
msg["To"] = to
msg["Subject"] = subject
msg.attach(MIMEText(body, "plain"))
if attachment_path and os.path.exists(attachment_path):
part = MIMEBase("application", "octet-stream")
with open(attachment_path, "rb") as f:
part.set_payload(f.read())
encoders.encode_base64(part)
part.add_header("Content-Disposition",
f'attachment; filename="{os.path.basename(attachment_path)}"')
msg.attach(part)
server = smtplib.SMTP("smtp.gmail.com", 587)
server.starttls()
server.login(sender, password)
server.send_message(msg)
server.quit()
send_email("your.email@gmail.com", "jfff kdzn llka srvw",
"recipient@example.com", "Subject", "Body",
"/path/to/resume.pdf")import imaplib, email
from email.header import decode_header
mail = imaplib.IMAP4_SSL("imap.gmail.com")
mail.login("your.email@gmail.com", "jfff kdzn llka srvw")
mail.select("inbox")
status, ids = mail.search(None, "UNSEEN")
ids = ids[0].split()[-5:] if ids[0] else []
ids.reverse()
for eid in ids:
status, data = mail.fetch(eid, "(RFC822)")
msg = email.message_from_bytes(data[0][1])
subject, enc = decode_header(msg["Subject"])[0]
if isinstance(subject, bytes):
subject = subject.decode(enc or "utf-8", errors="replace")
print(f"From: {msg['From']}")
print(f"Subject: {subject}")
print(f"Date: {msg['Date']}")
mail.logout()| Item | Value |
|---|---|
| SMTP Server | smtp.gmail.com:587 (STARTTLS) |
| IMAP Server | imap.gmail.com:993 (SSL) |
| Auth | Full email + App Password (not regular password) |
| App Password format | 16 chars, space-separated groups of 4 |
| Approach | Pros | Cons |
|---|---|---|
| App Password | Simple, no OAuth flow, immediate | Requires 2FA, single-purpose |
| OAuth 2.0 | More secure, no 2FA required | Setup complexity, refresh tokens |
Full working script at: /home/mysyntax/Documents/me_2025/send_email.py
It handles:
- CLI args:
recipient,subject,body - Interactive prompts when args missing
- Env var or prompted credentials
- Resume PDF attachment