email testing
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
# OpenRouter API Configuration
|
||||
OPENROUTER_API_KEY=your_api_key_here
|
||||
# No quotes needed - just paste your key directly
|
||||
OPENROUTER_API_KEY=sk-or-v1-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
|
||||
# Optional: Your site info for OpenRouter rankings
|
||||
OPENROUTER_SITE_URL=https://your-site.com
|
||||
OPENROUTER_SITE_NAME=YourSiteName
|
||||
|
||||
# SMTP Credentials for your mail server
|
||||
# No quotes needed - even if your password contains special characters
|
||||
SMTP_USERNAME=your-email@yourdomain.com
|
||||
SMTP_PASSWORD=your-smtp-password
|
||||
|
||||
|
||||
161
MODELS.md
Normal file
161
MODELS.md
Normal file
@@ -0,0 +1,161 @@
|
||||
# OpenRouter Model Reference
|
||||
|
||||
Quick reference for choosing the right AI model for News Agent.
|
||||
|
||||
## Recommended Models
|
||||
|
||||
### Best Overall: `google/gemini-flash-1.5-8b`
|
||||
- **Cost:** ~$0.05-0.15/day
|
||||
- **Quality:** Excellent
|
||||
- **Speed:** Very fast
|
||||
- **Best for:** Production use, daily digests
|
||||
|
||||
### Best Free: `google/gemini-2.0-flash-exp:free`
|
||||
- **Cost:** FREE
|
||||
- **Quality:** Good (experimental)
|
||||
- **Speed:** Fast
|
||||
- **Best for:** Testing, low-budget setups
|
||||
- **Note:** Experimental, may change
|
||||
|
||||
### Budget Option: `meta-llama/llama-3.1-8b-instruct:free`
|
||||
- **Cost:** FREE
|
||||
- **Quality:** Decent
|
||||
- **Speed:** Moderate
|
||||
- **Best for:** Testing, development
|
||||
|
||||
### High Quality: `anthropic/claude-3.5-haiku`
|
||||
- **Cost:** ~$0.10-0.25/day
|
||||
- **Quality:** Excellent
|
||||
- **Speed:** Fast
|
||||
- **Best for:** When quality matters most
|
||||
|
||||
### OpenAI Option: `openai/gpt-4o-mini`
|
||||
- **Cost:** ~$0.08-0.20/day
|
||||
- **Quality:** Very good
|
||||
- **Speed:** Fast
|
||||
- **Best for:** Balanced quality/cost
|
||||
|
||||
## How to Change Model
|
||||
|
||||
Edit `config.yaml`:
|
||||
|
||||
```yaml
|
||||
ai:
|
||||
model: "google/gemini-flash-1.5-8b" # Change this line
|
||||
```
|
||||
|
||||
## Full Model List
|
||||
|
||||
See all available models at: https://openrouter.ai/models
|
||||
|
||||
Filter by:
|
||||
- **Free models** - Search for `:free` suffix
|
||||
- **Context length** - Important for long articles
|
||||
- **Supported features** - JSON mode, function calling, etc.
|
||||
|
||||
## Cost Comparison (Daily Estimates)
|
||||
|
||||
Based on processing ~50 articles/day with 15 summaries:
|
||||
|
||||
| Model | Daily Cost | Monthly Cost | Quality |
|
||||
|-------|-----------|--------------|---------|
|
||||
| `google/gemini-2.0-flash-exp:free` | $0.00 | $0.00 | Good |
|
||||
| `meta-llama/llama-3.1-8b-instruct:free` | $0.00 | $0.00 | Decent |
|
||||
| `google/gemini-flash-1.5-8b` | $0.05-0.15 | $1.50-4.50 | Excellent |
|
||||
| `openai/gpt-4o-mini` | $0.08-0.20 | $2.40-6.00 | Very Good |
|
||||
| `anthropic/claude-3.5-haiku` | $0.10-0.25 | $3.00-7.50 | Excellent |
|
||||
| `openai/gpt-4o` | $0.50-1.50 | $15-45 | Outstanding |
|
||||
|
||||
*Costs vary based on article length and quantity*
|
||||
|
||||
## Testing a New Model
|
||||
|
||||
1. Update `config.yaml`:
|
||||
```yaml
|
||||
ai:
|
||||
model: "new-model-name"
|
||||
```
|
||||
|
||||
2. Run a test:
|
||||
```bash
|
||||
source .venv/bin/activate
|
||||
python -m src.main
|
||||
```
|
||||
|
||||
3. Check quality of summaries in the email
|
||||
|
||||
4. Monitor costs at: https://openrouter.ai/activity
|
||||
|
||||
## Model Selection Tips
|
||||
|
||||
### Choose FREE models if:
|
||||
- You're testing the system
|
||||
- Cost is a major concern
|
||||
- Article quality/accuracy is less critical
|
||||
|
||||
### Choose PAID models if:
|
||||
- You want best quality summaries
|
||||
- You need reliable daily digests
|
||||
- You value accurate relevance scoring
|
||||
|
||||
### Performance vs Cost:
|
||||
- **Gemini Flash 1.5-8b** - Best balance
|
||||
- **Claude Haiku** - Best quality for cost
|
||||
- **GPT-4o-mini** - Good all-rounder
|
||||
- **Free models** - Testing/development
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Error: "No endpoints found for [model]"
|
||||
|
||||
The model name is incorrect or not available on OpenRouter.
|
||||
|
||||
**Solution:**
|
||||
1. Check model name at: https://openrouter.ai/models
|
||||
2. Copy exact model ID (e.g., `google/gemini-flash-1.5-8b`)
|
||||
3. Update `config.yaml`
|
||||
4. Restart the service
|
||||
|
||||
### Model Seems Slow
|
||||
|
||||
Some models are slower than others.
|
||||
|
||||
**Solutions:**
|
||||
- Try `google/gemini-flash-1.5-8b` (fastest)
|
||||
- Reduce `max_articles` in config (process fewer articles)
|
||||
- Use cheaper/faster models for filtering, premium for summarization
|
||||
|
||||
### Poor Summary Quality
|
||||
|
||||
The model might not be good at summarization.
|
||||
|
||||
**Solutions:**
|
||||
- Try `anthropic/claude-3.5-haiku` (excellent summarization)
|
||||
- Adjust prompts in `src/ai/prompts.py`
|
||||
- Increase temperature for more creative summaries
|
||||
- Try different models
|
||||
|
||||
### High Costs
|
||||
|
||||
You're using an expensive model or processing too many articles.
|
||||
|
||||
**Solutions:**
|
||||
1. Switch to cheaper model (Gemini Flash or free options)
|
||||
2. Increase `min_score` to filter more aggressively
|
||||
3. Reduce `max_articles` limit
|
||||
4. Monitor usage: https://openrouter.ai/activity
|
||||
|
||||
## Advanced: Using Different Models for Different Tasks
|
||||
|
||||
You could modify the code to use:
|
||||
- **Fast/cheap model** for filtering (scoring articles)
|
||||
- **High-quality model** for summarization
|
||||
|
||||
Edit `src/main.py` to instantiate different clients for different tasks.
|
||||
|
||||
## Need Help?
|
||||
|
||||
- **Model pricing:** https://openrouter.ai/models (click model for details)
|
||||
- **API docs:** https://openrouter.ai/docs
|
||||
- **Check costs:** https://openrouter.ai/activity
|
||||
- **Model comparison:** Test different models and compare results
|
||||
23
README.md
23
README.md
@@ -102,7 +102,7 @@ email:
|
||||
- **SendGrid**: `smtp.sendgrid.net:587`, use API key as password
|
||||
|
||||
Optionally adjust:
|
||||
- AI model (default: `google/gemini-flash-1.5` - fast and cheap)
|
||||
- AI model (default: `google/gemini-flash-1.5-8b` - fast and cheap)
|
||||
- Filtering threshold (default: 6.5/10)
|
||||
- Max articles per digest (default: 15)
|
||||
- RSS sources (add/remove feeds)
|
||||
@@ -204,11 +204,15 @@ sources:
|
||||
### AI Configuration
|
||||
|
||||
**Models** (from cheap to expensive):
|
||||
- `google/gemini-flash-1.5` - Fast, cheap, good quality (recommended)
|
||||
- `meta-llama/llama-3.1-8b-instruct` - Very cheap
|
||||
- `google/gemini-flash-1.5-8b` - Fast, cheap, good quality (recommended)
|
||||
- `google/gemini-2.0-flash-exp:free` - Free, experimental (good for testing)
|
||||
- `meta-llama/llama-3.1-8b-instruct:free` - Free, decent quality
|
||||
- `anthropic/claude-3.5-haiku` - Better quality, slightly more expensive
|
||||
- `openai/gpt-4o-mini` - Good quality, moderate price
|
||||
|
||||
See **[MODELS.md](MODELS.md)** for detailed comparison and selection guide.
|
||||
Full list at: https://openrouter.ai/models
|
||||
|
||||
**Filtering:**
|
||||
```yaml
|
||||
ai:
|
||||
@@ -263,9 +267,16 @@ systemctl --user restart news-agent.timer
|
||||
|
||||
### API Errors
|
||||
|
||||
**Error: "No endpoints found for [model]"**
|
||||
- The model name is incorrect
|
||||
- Check correct model names in `MODELS.md`
|
||||
- Update `config.yaml` with correct model ID
|
||||
|
||||
**Other API errors:**
|
||||
1. **Verify API key in `.env`**
|
||||
2. **Check OpenRouter credit balance:** https://openrouter.ai/credits
|
||||
3. **Check rate limits in logs**
|
||||
4. **Try a different model** (see `MODELS.md`)
|
||||
|
||||
### Service Not Running
|
||||
|
||||
@@ -290,12 +301,16 @@ python -m src.main
|
||||
|
||||
## Cost Estimation
|
||||
|
||||
Using `google/gemini-flash-1.5` (recommended):
|
||||
Using `google/gemini-flash-1.5-8b` (recommended):
|
||||
|
||||
- **Daily:** ~$0.05-0.15 (varies by article count)
|
||||
- **Monthly:** ~$1.50-4.50
|
||||
- **Yearly:** ~$18-54
|
||||
|
||||
**Free Options:**
|
||||
- `google/gemini-2.0-flash-exp:free` - Completely free (experimental)
|
||||
- `meta-llama/llama-3.1-8b-instruct:free` - Completely free
|
||||
|
||||
Factors affecting cost:
|
||||
- Number of new articles
|
||||
- Content length
|
||||
|
||||
@@ -23,7 +23,21 @@ SMTP_USERNAME=your-email@yourdomain.com
|
||||
SMTP_PASSWORD=your-password-or-app-password
|
||||
```
|
||||
|
||||
**Security Note:** The `.env` file is gitignored and should never be committed to version control.
|
||||
**Important Notes:**
|
||||
- **NO quotes needed** - Values should be plain text without quotes
|
||||
- **Special characters are OK** - Passwords with `!@#$%` etc. work fine
|
||||
- **Security:** The `.env` file is gitignored and should never be committed to version control
|
||||
|
||||
**Examples:**
|
||||
```env
|
||||
# Correct - no quotes
|
||||
SMTP_USERNAME=admin@example.com
|
||||
SMTP_PASSWORD=P@ssw0rd!123
|
||||
|
||||
# Wrong - don't use quotes
|
||||
SMTP_USERNAME="admin@example.com" # ❌
|
||||
SMTP_PASSWORD='P@ssw0rd!123' # ❌
|
||||
```
|
||||
|
||||
### 2. Edit `config.yaml`
|
||||
|
||||
|
||||
14
config.yaml
14
config.yaml
@@ -61,9 +61,9 @@ sources:
|
||||
url: "https://www.engadget.com/rss.xml"
|
||||
category: "gadgets"
|
||||
|
||||
- name: "AnandTech"
|
||||
url: "https://www.anandtech.com/rss/"
|
||||
category: "gadgets"
|
||||
#- name: "AnandTech"
|
||||
# url: "https://www.anandtech.com/rss/"
|
||||
# category: "gadgets"
|
||||
|
||||
- name: "Tom's Hardware"
|
||||
url: "https://www.tomshardware.com/feeds/all"
|
||||
@@ -72,10 +72,12 @@ sources:
|
||||
ai:
|
||||
provider: "openrouter"
|
||||
base_url: "https://openrouter.ai/api/v1"
|
||||
model: "google/gemini-flash-1.5"
|
||||
# Alternative models:
|
||||
model: "google/gemini-flash-1.5-8b"
|
||||
# Alternative models (see https://openrouter.ai/models for full list):
|
||||
# - "google/gemini-2.0-flash-exp:free" (free, experimental)
|
||||
# - "anthropic/claude-3.5-haiku" (better quality, slightly more expensive)
|
||||
# - "meta-llama/llama-3.1-8b-instruct" (very cheap)
|
||||
# - "meta-llama/llama-3.1-8b-instruct:free" (free, good quality)
|
||||
# - "openai/gpt-4o-mini" (good quality, moderate price)
|
||||
|
||||
filtering:
|
||||
enabled: true
|
||||
|
||||
109
src/test_email_simple.py
Normal file
109
src/test_email_simple.py
Normal file
@@ -0,0 +1,109 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Simple email test - run with: python -m src.test_email_simple"""
|
||||
|
||||
from datetime import datetime
|
||||
from .config import get_config
|
||||
from .logger import setup_logger
|
||||
from .email.sender import EmailSender
|
||||
|
||||
|
||||
def main():
|
||||
"""Send a test email"""
|
||||
setup_logger()
|
||||
config = get_config()
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("Testing Email Configuration")
|
||||
print("=" * 60)
|
||||
|
||||
print(f"\nSMTP Server: {config.email.smtp.host}:{config.email.smtp.port}")
|
||||
print(f"TLS: {config.email.smtp.use_tls}")
|
||||
print(f"SSL: {config.email.smtp.use_ssl}")
|
||||
print(f"From: {config.email.from_}")
|
||||
print(f"To: {config.email.to}")
|
||||
print(f"Username: {config.env.smtp_username or '(not set)'}")
|
||||
print(f"Password: {'***' if config.env.smtp_password else '(not set)'}")
|
||||
|
||||
print("\nSending test email...")
|
||||
|
||||
# Create test email content
|
||||
subject = "News Agent Test Email"
|
||||
|
||||
html_content = f"""
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
body {{ font-family: Arial, sans-serif; padding: 20px; }}
|
||||
.header {{ background-color: #2563eb; color: white; padding: 20px; border-radius: 8px; }}
|
||||
.content {{ margin-top: 20px; line-height: 1.6; }}
|
||||
.success {{ color: #16a34a; font-weight: bold; }}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="header">
|
||||
<h1>✓ News Agent Email Test</h1>
|
||||
</div>
|
||||
<div class="content">
|
||||
<p class="success">Congratulations! Your email configuration is working correctly.</p>
|
||||
|
||||
<p><strong>Test Details:</strong></p>
|
||||
<ul>
|
||||
<li>Date: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}</li>
|
||||
<li>SMTP Server: {config.email.smtp.host}:{config.email.smtp.port}</li>
|
||||
<li>Encryption: {"TLS" if config.email.smtp.use_tls else "SSL" if config.email.smtp.use_ssl else "None"}</li>
|
||||
</ul>
|
||||
|
||||
<p>Your News Agent is now ready to send daily digests!</p>
|
||||
|
||||
<hr>
|
||||
<p style="color: #6b7280; font-size: 12px;">
|
||||
This is a test email from News Agent. If you received this,
|
||||
your SMTP configuration is correct and you should start receiving
|
||||
daily news digests.
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
text_content = f"""
|
||||
News Agent Email Test
|
||||
=====================
|
||||
|
||||
✓ Congratulations! Your email configuration is working correctly.
|
||||
|
||||
Test Details:
|
||||
- Date: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
|
||||
- SMTP Server: {config.email.smtp.host}:{config.email.smtp.port}
|
||||
- Encryption: {"TLS" if config.email.smtp.use_tls else "SSL" if config.email.smtp.use_ssl else "None"}
|
||||
|
||||
Your News Agent is now ready to send daily digests!
|
||||
|
||||
---
|
||||
This is a test email from News Agent. If you received this,
|
||||
your SMTP configuration is correct and you should start receiving
|
||||
daily news digests.
|
||||
"""
|
||||
|
||||
# Send email
|
||||
sender = EmailSender()
|
||||
success = sender.send(subject, html_content, text_content)
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
if success:
|
||||
print("✓ SUCCESS! Test email sent successfully!")
|
||||
print(f"✓ Check your inbox: {config.email.to}")
|
||||
else:
|
||||
print("✗ FAILED! Email could not be sent.")
|
||||
print("✗ Check the error messages above.")
|
||||
print("\nTroubleshooting steps:")
|
||||
print("1. Verify SMTP credentials in .env file")
|
||||
print("2. Check SMTP server settings in config.yaml")
|
||||
print("3. Review logs: cat data/logs/news-agent.log")
|
||||
print("4. See SMTP_CONFIG.md for detailed troubleshooting")
|
||||
print("=" * 60 + "\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
132
test_email.py
Normal file
132
test_email.py
Normal file
@@ -0,0 +1,132 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Quick email sending test script"""
|
||||
|
||||
import sys
|
||||
from datetime import datetime
|
||||
|
||||
# Add src to path
|
||||
sys.path.insert(0, "src")
|
||||
|
||||
from src.config import get_config
|
||||
from src.logger import setup_logger
|
||||
from src.email.sender import EmailSender
|
||||
|
||||
|
||||
def test_email():
|
||||
"""Send a test email"""
|
||||
setup_logger()
|
||||
config = get_config()
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("Testing Email Configuration")
|
||||
print("=" * 60)
|
||||
|
||||
print(f"\nSMTP Server: {config.email.smtp.host}:{config.email.smtp.port}")
|
||||
print(f"TLS: {config.email.smtp.use_tls}")
|
||||
print(f"SSL: {config.email.smtp.use_ssl}")
|
||||
print(f"From: {config.email.from_}")
|
||||
print(f"To: {config.email.to}")
|
||||
print(f"Username: {config.env.smtp_username or '(not set)'}")
|
||||
print(f"Password: {'***' if config.env.smtp_password else '(not set)'}")
|
||||
|
||||
print("\nSending test email...")
|
||||
|
||||
# Create test email content
|
||||
subject = "News Agent Test Email"
|
||||
|
||||
html_content = (
|
||||
"""
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; padding: 20px; }
|
||||
.header { background-color: #2563eb; color: white; padding: 20px; border-radius: 8px; }
|
||||
.content { margin-top: 20px; line-height: 1.6; }
|
||||
.success { color: #16a34a; font-weight: bold; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="header">
|
||||
<h1>✓ News Agent Email Test</h1>
|
||||
</div>
|
||||
<div class="content">
|
||||
<p class="success">Congratulations! Your email configuration is working correctly.</p>
|
||||
|
||||
<p><strong>Test Details:</strong></p>
|
||||
<ul>
|
||||
<li>Date: """
|
||||
+ datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
+ """</li>
|
||||
<li>SMTP Server: """
|
||||
+ f"{config.email.smtp.host}:{config.email.smtp.port}"
|
||||
+ """</li>
|
||||
<li>Encryption: """
|
||||
+ ("TLS" if config.email.smtp.use_tls else "SSL" if config.email.smtp.use_ssl else "None")
|
||||
+ """</li>
|
||||
</ul>
|
||||
|
||||
<p>Your News Agent is now ready to send daily digests!</p>
|
||||
|
||||
<hr>
|
||||
<p style="color: #6b7280; font-size: 12px;">
|
||||
This is a test email from News Agent. If you received this,
|
||||
your SMTP configuration is correct and you should start receiving
|
||||
daily news digests.
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
)
|
||||
|
||||
text_content = f"""
|
||||
News Agent Email Test
|
||||
=====================
|
||||
|
||||
✓ Congratulations! Your email configuration is working correctly.
|
||||
|
||||
Test Details:
|
||||
- Date: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
|
||||
- SMTP Server: {config.email.smtp.host}:{config.email.smtp.port}
|
||||
- Encryption: {"TLS" if config.email.smtp.use_tls else "SSL" if config.email.smtp.use_ssl else "None"}
|
||||
|
||||
Your News Agent is now ready to send daily digests!
|
||||
|
||||
---
|
||||
This is a test email from News Agent. If you received this,
|
||||
your SMTP configuration is correct and you should start receiving
|
||||
daily news digests.
|
||||
"""
|
||||
|
||||
# Send email
|
||||
sender = EmailSender()
|
||||
success = sender.send(subject, html_content, text_content)
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
if success:
|
||||
print("✓ SUCCESS! Test email sent successfully!")
|
||||
print(f"✓ Check your inbox: {config.email.to}")
|
||||
else:
|
||||
print("✗ FAILED! Email could not be sent.")
|
||||
print("✗ Check the error messages above.")
|
||||
print("\nTroubleshooting steps:")
|
||||
print("1. Verify SMTP credentials in .env file")
|
||||
print("2. Check SMTP server settings in config.yaml")
|
||||
print("3. Review logs: cat data/logs/news-agent.log")
|
||||
print("4. See SMTP_CONFIG.md for detailed troubleshooting")
|
||||
print("=" * 60 + "\n")
|
||||
|
||||
return success
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
success = test_email()
|
||||
sys.exit(0 if success else 1)
|
||||
except Exception as e:
|
||||
print(f"\n✗ ERROR: {e}")
|
||||
import traceback
|
||||
|
||||
traceback.print_exc()
|
||||
sys.exit(1)
|
||||
Reference in New Issue
Block a user