This guide shows you how to use OpenPlugin to build a complete email drafting and sending application that uses LLM (like GPT-4) to compose emails and SMTP to send them.
┌─────────────────────────────────────────────────────────┐
│ Your Application │
│ (email_app.py, web app, API, script, etc.) │
└────────────────────┬────────────────────────────────────┘
│
┌────────────┴────────────┐
│ │
▼ ▼
┌──────────────┐ ┌──────────────┐
│ OpenPlugin │ │ EmailSender │
│ Framework │ │ (SMTP) │
└──────┬───────┘ └──────────────┘
│
├─── PluginManager (loads plugins)
├─── Email Plugin (draft/send commands)
└─── OpenAIProvider (LLM calls)
Defines two commands:
draft.md: Instructions for LLM to draft emailssend.md: Instructions for email sending logic
Main application class that:
- Loads the email plugin
- Uses LLM to draft emails
- Sends emails via SMTP
Utility class for SMTP email sending.
git clone https://github.com/VishwasK/openplugin
cd openplugin
pip install -r requirements.txt# Required
export OPENAI_API_KEY="sk-your-openai-key"
# For email sending (Gmail example)
export SMTP_HOST="smtp.gmail.com"
export SMTP_PORT="587"
export SMTP_USERNAME="your-email@gmail.com"
export SMTP_PASSWORD="your-app-password"Gmail Setup:
- Enable 2-Factor Authentication
- Generate App Password: Google Account → Security → App Passwords
- Use the generated password (not your regular password)
python examples/email_app.pyimport asyncio
from examples.email_app import EmailApp
import os
async def main():
app = EmailApp(openai_api_key=os.getenv("OPENAI_API_KEY"))
draft = await app.draft_email(
recipient="Sarah Johnson",
purpose="Follow up on Q4 project timeline",
tone="professional",
key_points=[
"Thank her for the meeting",
"Confirm deliverables",
"Request feedback on timeline"
]
)
print(draft)
await app.shutdown()
asyncio.run(main())async def main():
app = EmailApp(openai_api_key=os.getenv("OPENAI_API_KEY"))
result = await app.draft_and_send(
to="sarah@example.com",
recipient_name="Sarah Johnson",
purpose="Project update",
tone="professional",
key_points=["Milestone 1 complete", "Next steps"],
from_email="you@example.com"
)
if result["send"]["success"]:
print("✅ Email sent!")
else:
print(f"❌ Error: {result['send']['message']}")
await app.shutdown()from openplugin import PluginManager, OpenAIProvider
from openplugin.utils import EmailSender
class MyEmailService:
def __init__(self):
self.manager = PluginManager(plugins_dir="./plugins")
self.manager.load_plugins()
self.provider = OpenAIProvider(api_key="your-key")
self.email_sender = EmailSender()
async def send_followup(self, customer_email, meeting_notes):
# Draft email using LLM
draft = await self.manager.execute_command(
"email-plugin",
"draft",
provider=self.provider,
user_input=f"""
Draft a follow-up email to {customer_email} based on these meeting notes:
{meeting_notes}
Tone: Professional
Include: Key action items and next steps
"""
)
# Extract subject and body (you'd parse this properly)
subject = "Follow-up: Meeting Notes"
body = draft
# Send
return self.email_sender.send_email(
to=customer_email,
subject=subject,
body=body
)manager = PluginManager(plugins_dir="./plugins")
manager.load_plugins() # Discovers and loads email-pluginThe manager:
- Scans
plugins/directory - Finds
email-plugin/.claude-plugin/plugin.json - Loads command definitions from
commands/
draft = await manager.execute_command(
"email-plugin",
"draft",
provider=provider,
user_input="Draft email to John about project..."
)Behind the scenes:
- Finds "draft" command in email-plugin
- Reads
commands/draft.md(command instructions) - Sends your input + command instructions to OpenAI
- Returns LLM-generated email draft
email_sender.send_email(to="...", subject="...", body="...")The EmailSender:
- Connects to SMTP server
- Authenticates with credentials
- Sends email
- Returns success/error status
provider = OpenAIProvider(
api_key="your-key",
model="gpt-3.5-turbo" # or "gpt-4", etc.
)Edit plugins/email-plugin/commands/draft.md to change:
- Email format
- Tone options
- Required fields
- Output structure
Create plugins/email-plugin/commands/schedule.md:
# Schedule Email Command
Schedules an email to be sent later.
## Usage
...Then use it:
await manager.execute_command(
"email-plugin",
"schedule",
provider=provider,
user_input="..."
)email_sender = EmailSender(
smtp_host="smtp.sendgrid.net",
smtp_port=587,
smtp_username="apikey",
smtp_password="your-sendgrid-key"
)from flask import Flask, request, jsonify
app = Flask(__name__)
email_app = EmailApp(openai_api_key=OPENAI_KEY)
@app.route('/draft-email', methods=['POST'])
async def draft_email():
data = request.json
draft = await email_app.draft_email(
recipient=data['recipient'],
purpose=data['purpose'],
tone=data.get('tone', 'professional')
)
return jsonify({"draft": draft})import click
@click.command()
@click.option('--to', required=True)
@click.option('--purpose', required=True)
def send_email(to, purpose):
app = EmailApp(openai_api_key=os.getenv("OPENAI_API_KEY"))
result = asyncio.run(app.draft_and_send(...))
click.echo(result)import schedule
def send_daily_report():
app = EmailApp(...)
asyncio.run(app.draft_and_send(
to="team@company.com",
purpose="Daily report",
...
))
schedule.every().day.at("09:00").do(send_daily_report)try:
draft = await app.draft_email(...)
except Exception as e:
print(f"Drafting failed: {e}")
# Fallback to template
try:
result = app.email_sender.send_email(...)
if not result["success"]:
print(f"Send failed: {result['message']}")
except Exception as e:
print(f"SMTP error: {e}")- Validate Input: Check email addresses before sending
- Handle Errors: Always wrap LLM and SMTP calls in try/except
- Rate Limiting: Respect OpenAI API rate limits
- Security: Never hardcode credentials
- Testing: Test with a test email account first
- Logging: Log all email operations for debugging
- Set
SMTP_USERNAMEandSMTP_PASSWORDenvironment variables - Or pass them to
EmailSender()constructor
- Ensure plugin is in
plugins/email-plugin/ - Check
plugin.jsonexists and is valid
- Verify
OPENAI_API_KEYis set correctly - Check API key has sufficient credits
- Verify model name is correct
- Check SMTP credentials
- Verify firewall allows SMTP connections
- For Gmail: Use App Password, not regular password
- Read
docs/EMAIL_APP_TUTORIAL.mdfor detailed walkthrough - Check
USE_CASES.mdfor more application ideas - Explore
examples/for more examples - Create your own plugins and commands!
- GitHub Issues: https://github.com/VishwasK/openplugin/issues
- Documentation: See
docs/directory - Examples: See
examples/directory